Skip to content

wysaid/CameraCapture

Repository files navigation

ccap (CameraCapture)

Windows Build macOS Build Linux Build Rust CI License: MIT C++17 C99 Platform

English | 中文

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

Table of Contents

Features

  • 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)
  • 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)
  • Production Ready: Comprehensive test suite with 95%+ accuracy validation
  • Virtual Camera Support: Compatible with OBS Virtual Camera and similar tools

Quick Start

Installation

  1. Build and install from source (on Windows, use git-bash):

    git clone https://github.com/wysaid/CameraCapture.git
    cd CameraCapture
    ./scripts/build_and_install.sh
  2. Integrate directly using CMake FetchContent:

    Add the following to your CMakeLists.txt:

    include(FetchContent)
    FetchContent_Declare(
        ccap
        GIT_REPOSITORY https://github.com/wysaid/CameraCapture.git
        GIT_TAG        main
    )
    FetchContent_MakeAvailable(ccap)
    
    target_link_libraries(your_app PRIVATE ccap::ccap)

    You can then use ccap headers and features directly in your project.

  3. Install and use via Homebrew on macOS:

    • First, install the binary with Homebrew:

      brew tap wysaid/ccap
      brew install ccap
    • Then, use it in CMake:

      find_package(ccap REQUIRED)
      target_link_libraries(your_app ccap::ccap)

Basic Usage

ccap provides both complete C++ and pure C language interfaces to meet different project and development requirements:

  • C++ Interface: Modern C++ API with smart pointers, lambda callbacks, and other advanced features
  • Pure C Interface: Fully compatible with C99 standard, supporting language bindings and traditional C project integration

C++ Interface

#include <ccap.h>

int main() {
    ccap::Provider provider;
    
    // List available cameras
    auto devices = provider.findDeviceNames();
    for (size_t i = 0; i < devices.size(); ++i) {
        printf("[%zu] %s\n", i, devices[i].c_str());
    }
    
    // Open and start camera
    if (provider.open("", true)) {  // Empty string = default camera
        auto frame = provider.grab(3000);  // 3 second timeout
        if (frame) {
            printf("Captured: %dx%d, %s format\n", 
                   frame->width, frame->height,
                   ccap::pixelFormatToString(frame->pixelFormat).data());
        }
    }
    return 0;
}
Error Handling in C++

Starting from v1.2.0, ccap uses a global error callback system for simplified error handling across all camera operations:

#include <ccap.h>
#include <iostream>

int main() {
    // Set error callback to receive detailed error information
    ccap::setErrorCallback([](ccap::ErrorCode errorCode, const std::string& description) {
        std::cerr << "Camera Error - Code: " << static_cast<int>(errorCode) 
                  << ", Description: " << description << std::endl;
    });
    
    ccap::Provider provider;
    
    // Camera operations - errors will trigger the global callback
    if (!provider.open("", true)) {
        std::cerr << "Failed to open camera" << std::endl;
    }
    
    return 0;
}

Available error codes include:

  • ErrorCode::NoDeviceFound - No camera device found
  • ErrorCode::InvalidDevice - Invalid device name or index
  • ErrorCode::DeviceOpenFailed - Camera open failed
  • ErrorCode::DeviceStartFailed - Camera start failed
  • ErrorCode::UnsupportedResolution - Unsupported resolution
  • ErrorCode::UnsupportedPixelFormat - Unsupported pixel format
  • ErrorCode::FrameCaptureTimeout - Frame capture timeout
  • ErrorCode::FrameCaptureFailed - Frame capture failed

Pure C Interface

#include <ccap_c.h>
#include <ccap_utils_c.h>

int main() {
    // Create provider
    CcapProvider* provider = ccap_provider_create();
    if (!provider) return -1;
    
    // Find available devices
    CcapDeviceNamesList deviceList;
    if (ccap_provider_find_device_names_list(provider, &deviceList)) {
        printf("Found %zu camera device(s):\n", deviceList.deviceCount);
        for (size_t i = 0; i < deviceList.deviceCount; i++) {
            printf("  %zu: %s\n", i, deviceList.deviceNames[i]);
        }
    }
    
    // Open default camera
    if (ccap_provider_open(provider, NULL, false)) {
        // Set output format
        ccap_provider_set_property(provider, CCAP_PROPERTY_PIXEL_FORMAT_OUTPUT, 
                                   CCAP_PIXEL_FORMAT_BGR24);
        
        // Start capture
        if (ccap_provider_start(provider)) {
            // Grab a frame
            CcapVideoFrame* frame = ccap_provider_grab(provider, 3000);
            if (frame) {
                CcapVideoFrameInfo frameInfo;
                if (ccap_video_frame_get_info(frame, &frameInfo)) {
                    // Get pixel format string
                    char formatStr[64];
                    ccap_pixel_format_to_string(frameInfo.pixelFormat, formatStr, sizeof(formatStr));
                    
                    printf("Captured: %dx%d, format=%s\n", 
                           frameInfo.width, frameInfo.height, formatStr);
                }
                ccap_video_frame_release(frame);
            }
        }
        
        ccap_provider_stop(provider);
        ccap_provider_close(provider);
    }
    
    ccap_provider_destroy(provider);
    return 0;
}

Rust Bindings

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

Quick install:

cargo add ccap-rs

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

[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:

# Build with CLI tool enabled
mkdir build && cd build
cmake .. -DCCAP_BUILD_CLI=ON
cmake --build .

# List available cameras
./ccap --list-devices

# Capture 5 images from default camera
./ccap -c 5 -o ./captures

# Real-time preview (requires GLFW)
./ccap --preview

# Play video file and extract frames
./ccap -i video.mp4 -c 30 -o ./frames

# Video preview with playback controls
./ccap -i video.mp4 --preview --speed 1.0

Key Features:

  • 📷 List and select camera devices
  • 🎯 Capture single or multiple images
  • 👁️ Real-time preview window (with GLFW)
  • 🎬 Video file playback and frame extraction
  • ⚙️ Configure resolution, format, and frame rate
  • 💾 Save images in various formats (JPEG, PNG, BMP, etc.)
  • ⏱️ Duration-based or count-based capture modes
  • 🔁 Video looping and playback speed control

For complete CLI documentation, see CLI Tool Guide.

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+
Linux GCC 7+ / Clang 6+ V4L2 (Linux 2.6+)

Build Requirements: CMake 3.14+ (3.31+ recommended for MSVC 2026), C++17 (C++ interface), C99 (C interface)

Supported Linux Distributions

  • Ubuntu/Debian - All versions with Linux 2.6+ kernel
  • CentOS/RHEL/Fedora - All versions with Linux 2.6+ kernel
  • SUSE/openSUSE - All versions with Linux 2.6+ kernel
  • Arch Linux - All versions
  • Alpine Linux - All versions
  • Embedded Linux - Any distribution with V4L2 support

Examples

Example Description Language Platform
0-print_camera / 0-print_camera_c List available cameras C++ / C Desktop
1-minimal_example / 1-minimal_example_c Basic frame capture C++ / C Desktop
2-capture_grab / 2-capture_grab_c Continuous capture C++ / C Desktop
3-capture_callback / 3-capture_callback_c Callback-based capture C++ / C Desktop
4-example_with_glfw / 4-example_with_glfw_c OpenGL rendering C++ / C Desktop
5-play_video / 5-play_video_c Video file playback C++ / C Windows/macOS
iOS Demo iOS application Objective-C++ iOS

Build and Run Examples

mkdir build && cd build
cmake .. -DCCAP_BUILD_EXAMPLES=ON
cmake --build .

# Run examples
./0-print_camera
./1-minimal_example

# Run the pure C variants (if you built C examples)
./0-print_camera_c
./1-minimal_example_c

Note: Each desktop example is available in both C++ (.cpp) and pure C (.c) variants. Use the filenames with a trailing _c (e.g. 1-minimal_example_c.c) for the C versions.

API Reference

ccap provides both complete C++ and pure C interfaces to meet different project requirements.

Core Classes

ccap::Provider

class Provider {
public:
    // Constructors
    Provider();
    Provider(std::string_view deviceName, std::string_view extraInfo = "");
    Provider(int deviceIndex, std::string_view extraInfo = "");
    
    // Device discovery
    std::vector<std::string> findDeviceNames();
    
    // Camera lifecycle
    bool open(std::string_view deviceName = "", bool autoStart = true);
    bool open(int deviceIndex, bool autoStart = true);
    bool isOpened() const;
    void close();
    
    // Capture control
    bool start();
    void stop();
    bool isStarted() const;
    
    // Frame capture
    std::shared_ptr<VideoFrame> grab(uint32_t timeoutInMs = 0xffffffff);
    void setNewFrameCallback(std::function<bool(const std::shared_ptr<VideoFrame>&)> callback);
    
    // Property configuration
    bool set(PropertyName prop, double value);
    template<class T> bool set(PropertyName prop, T value);
    double get(PropertyName prop);
    
    // Device info and advanced configuration
    std::optional<DeviceInfo> getDeviceInfo() const;
    bool isFileMode() const;  // Check if playing video file vs camera
    void setFrameAllocator(std::function<std::shared_ptr<Allocator>()> allocatorFactory);
    void setMaxAvailableFrameSize(uint32_t size);
    void setMaxCacheFrameSize(uint32_t size);
};

ccap::VideoFrame

struct VideoFrame {
    
    // Frame data
    uint8_t* data[3] = {};                  // Raw pixel data planes
    uint32_t stride[3] = {};                // Stride for each plane
    
    // Frame properties
    PixelFormat pixelFormat = PixelFormat::Unknown;  // Pixel format
    uint32_t width = 0;                     // Frame width in pixels
    uint32_t height = 0;                    // Frame height in pixels
    uint32_t sizeInBytes = 0;               // Total frame data size
    uint64_t timestamp = 0;                 // Frame timestamp in nanoseconds
    uint64_t frameIndex = 0;                // Unique incremental frame index
    FrameOrientation orientation = FrameOrientation::Default;  // Frame orientation
    
    // Memory management and platform features
    std::shared_ptr<Allocator> allocator;   // Memory allocator
    void* nativeHandle = nullptr;           // Platform-specific handle
};

Configuration

enum class PropertyName {
    Width, Height, FrameRate,
    PixelFormatInternal,        // Camera's internal format
    PixelFormatOutput,          // Output format (with conversion)
    FrameOrientation,
    
    // Video file playback properties (file mode only)
    Duration,                   // Video duration in seconds (read-only)
    CurrentTime,                // Current playback time in seconds
    FrameCount,                 // Total frame count (read-only)
    PlaybackSpeed               // Playback speed multiplier (1.0 = normal speed)
};

enum class PixelFormat : uint32_t {
    Unknown = 0,
    NV12, NV12f,               // YUV 4:2:0 semi-planar
    I420, I420f,               // YUV 4:2:0 planar  
    RGB24, BGR24,              // 24-bit RGB/BGR
    RGBA32, BGRA32             // 32-bit RGBA/BGRA
};

Utility Functions

namespace ccap {
    // Hardware capabilities
    bool hasAVX2();
    bool hasAppleAccelerate();
    bool hasNEON();
    
    // Backend management
    ConvertBackend getConvertBackend();
    bool setConvertBackend(ConvertBackend backend);
    
    // Format utilities
    std::string_view pixelFormatToString(PixelFormat format);
    
    // File operations
    std::string dumpFrameToFile(VideoFrame* frame, std::string_view filename);
    
    // Logging
    enum class LogLevel { None, Error, Warning, Info, Verbose };
    void setLogLevel(LogLevel level);
}

Video File Playback

ccap supports playing video files using the same API as camera capture (Windows and macOS only):

#include <ccap.h>

ccap::Provider provider;

// Open video file - same API as camera
if (provider.open("/path/to/video.mp4", true)) {
    // Check if in file mode
    if (provider.isFileMode()) {
        // Get video properties
        double duration = provider.get(ccap::PropertyName::Duration);
        double frameCount = provider.get(ccap::PropertyName::FrameCount);
        double frameRate = provider.get(ccap::PropertyName::FrameRate);
        
        // Set playback speed (1.0 = normal speed)
        provider.set(ccap::PropertyName::PlaybackSpeed, 1.0);
        
        // Seek to specific time
        provider.set(ccap::PropertyName::CurrentTime, 10.0);  // Seek to 10 seconds
    }
    
    // Grab frames - same API as camera
    while (auto frame = provider.grab(3000)) {
        // Process frame...
    }
}

Supported video formats: MP4, AVI, MOV, MKV, and other formats supported by the platform's media framework.

Note: Video playback is currently not supported on Linux. This feature is available on Windows and macOS only.

OpenCV Integration

#include <ccap_opencv.h>

auto frame = provider.grab();
cv::Mat mat = ccap::convertRgbFrameToMat(*frame);

Fine-tuned Configuration

// Set specific resolution
provider.set(ccap::PropertyName::Width, 1920);
provider.set(ccap::PropertyName::Height, 1080);

// Set camera's internal format (helps clarify behavior and optimize performance)
provider.set(ccap::PropertyName::PixelFormatInternal, 
             static_cast<double>(ccap::PixelFormat::NV12));

// Set camera's output format
provider.set(ccap::PropertyName::PixelFormatOutput, 
             static_cast<double>(ccap::PixelFormat::BGR24));

C Language Interface

ccap provides a complete pure C language interface for C projects or scenarios requiring language bindings.

Core API

Provider Lifecycle
// Create and destroy Provider
CcapProvider* ccap_provider_create(void);
void ccap_provider_destroy(CcapProvider* provider);

// Device discovery
bool ccap_provider_find_device_names_list(CcapProvider* provider, 
                                          CcapDeviceNamesList* deviceList);

// Device management
bool ccap_provider_open(CcapProvider* provider, const char* deviceName, bool autoStart);
bool ccap_provider_open_by_index(CcapProvider* provider, int deviceIndex, bool autoStart);
void ccap_provider_close(CcapProvider* provider);
bool ccap_provider_is_opened(CcapProvider* provider);

// Capture control
bool ccap_provider_start(CcapProvider* provider);
void ccap_provider_stop(CcapProvider* provider);
bool ccap_provider_is_started(CcapProvider* provider);
Frame Capture and Processing
// Synchronous frame capture
CcapVideoFrame* ccap_provider_grab(CcapProvider* provider, uint32_t timeoutMs);
void ccap_video_frame_release(CcapVideoFrame* frame);

// Asynchronous callback
typedef bool (*CcapNewFrameCallback)(const CcapVideoFrame* frame, void* userData);
void ccap_provider_set_new_frame_callback(CcapProvider* provider, 
                                          CcapNewFrameCallback callback, void* userData);

// Frame information
typedef struct {
    uint8_t* data[3];           // Pixel data planes
    uint32_t stride[3];         // Stride for each plane
    uint32_t width;             // Width
    uint32_t height;            // Height
    uint32_t sizeInBytes;       // Total bytes
    uint64_t timestamp;         // Timestamp
    uint64_t frameIndex;        // Frame index
    CcapPixelFormat pixelFormat; // Pixel format
    CcapFrameOrientation orientation; // Orientation
} CcapVideoFrameInfo;

// Device names list
typedef struct {
    char deviceNames[CCAP_MAX_DEVICES][CCAP_MAX_DEVICE_NAME_LENGTH];
    size_t deviceCount;
} CcapDeviceNamesList;

bool ccap_video_frame_get_info(const CcapVideoFrame* frame, CcapVideoFrameInfo* info);
Property Configuration
// Property setting and getting
bool ccap_provider_set_property(CcapProvider* provider, CcapPropertyName prop, double value);
double ccap_provider_get_property(CcapProvider* provider, CcapPropertyName prop);

// Main properties
typedef enum {
    CCAP_PROPERTY_WIDTH = 0x10001,
    CCAP_PROPERTY_HEIGHT = 0x10002,
    CCAP_PROPERTY_FRAME_RATE = 0x20000,
    CCAP_PROPERTY_PIXEL_FORMAT_OUTPUT = 0x30002,
    CCAP_PROPERTY_FRAME_ORIENTATION = 0x40000
} CcapPropertyName;

// Pixel formats
typedef enum {
    CCAP_PIXEL_FORMAT_UNKNOWN = 0,
    CCAP_PIXEL_FORMAT_NV12 = 1 | (1 << 16),
    CCAP_PIXEL_FORMAT_NV12F = CCAP_PIXEL_FORMAT_NV12 | (1 << 17),
    CCAP_PIXEL_FORMAT_RGB24 = (1 << 3) | (1 << 18),
    CCAP_PIXEL_FORMAT_BGR24 = (1 << 4) | (1 << 18),
    CCAP_PIXEL_FORMAT_RGBA32 = CCAP_PIXEL_FORMAT_RGB24 | (1 << 19),
    CCAP_PIXEL_FORMAT_BGRA32 = CCAP_PIXEL_FORMAT_BGR24 | (1 << 19)
} CcapPixelFormat;
Error Handling

Starting from v1.2.0, ccap uses a global error callback system for simplified error handling:

// Error codes
typedef enum {
    CCAP_ERROR_NONE = 0,
    CCAP_ERROR_NO_DEVICE_FOUND = 0x1001,       // No camera device found
    CCAP_ERROR_INVALID_DEVICE = 0x1002,        // Invalid device name or index
    CCAP_ERROR_DEVICE_OPEN_FAILED = 0x1003,    // Camera open failed
    CCAP_ERROR_DEVICE_START_FAILED = 0x1004,   // Camera start failed
    CCAP_ERROR_UNSUPPORTED_RESOLUTION = 0x2001, // Unsupported resolution
    CCAP_ERROR_UNSUPPORTED_PIXEL_FORMAT = 0x2002, // Unsupported pixel format
    CCAP_ERROR_FRAME_CAPTURE_TIMEOUT = 0x3001, // Frame capture timeout
    CCAP_ERROR_FRAME_CAPTURE_FAILED = 0x3002,  // Frame capture failed
    // More error codes...
} CcapErrorCode;

// Error callback function
typedef void (*CcapErrorCallback)(CcapErrorCode errorCode, const char* errorDescription, void* userData);

// Set error callback
bool ccap_set_error_callback(CcapErrorCallback callback, void* userData);

// Get error description
const char* ccap_error_code_to_string(CcapErrorCode errorCode);

// Usage example
void error_callback(CcapErrorCode errorCode, const char* errorDescription, void* userData) {
    printf("Camera Error - Code: %d, Description: %s\n", (int)errorCode, errorDescription);
}

int main() {
    // Set error callback to receive error notifications
    ccap_set_error_callback(error_callback, NULL);
    
    CcapProvider* provider = ccap_provider_create();
    
    if (!ccap_provider_open_by_index(provider, 0, true)) {
        printf("Failed to open camera\n"); // Error callback will also be called
    }
    
    ccap_provider_destroy(provider);
    return 0;
}

Compilation and Linking

macOS
gcc -std=c99 your_code.c -o your_app \
    -I/path/to/ccap/include \
    -L/path/to/ccap/lib -lccap \
    -framework Foundation -framework AVFoundation \
    -framework CoreMedia -framework CoreVideo
Windows (MSVC)
cl your_code.c /I"path\to\ccap\include" \
   /link "path\to\ccap\lib\ccap.lib" ole32.lib oleaut32.lib uuid.lib
Linux
gcc -std=c99 your_code.c -o your_app \
    -I/path/to/ccap/include \
    -L/path/to/ccap/lib -lccap \
    -lpthread

Complete Documentation

For detailed usage instructions and examples of the C interface, see: C Interface Documentation

Additional C Utilities: For pixel format string conversion and file I/O functions, also include:

  • #include <ccap_utils_c.h> - provides ccap_pixel_format_to_string(), ccap_dump_frame_to_file()
  • #include <ccap_convert_c.h> - provides pixel format conversion functions

Testing

Comprehensive test suite with 50+ test cases covering all functionality:

  • Multi-backend testing (CPU, AVX2, Apple Accelerate, NEON)
  • Performance benchmarks and accuracy validation
  • 95%+ precision for pixel format conversions
./scripts/run_tests.sh

Build and Install

See BUILD_AND_INSTALL.md for complete instructions.

git clone https://github.com/wysaid/CameraCapture.git
cd CameraCapture
./scripts/build_and_install.sh

License

MIT License. See LICENSE for details.

About

ccap `(C)amera(CAP)ture` is a simple and easy-to-use C/C++ camera capture library designed to provide you with simple and efficient camera data access. It currently supports Windows macOS and Linux.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors