Skip to content

Commit 2817dde

Browse files
committed
[build] Enable NVIDIA Video Codec SDK support for hardware video decode/encode
Add NVCUVID and NVCUVENC support using the Video Codec SDK from the deps repository. This enables hardware-accelerated video decoding and encoding via NVIDIA GPUs.
1 parent 06a0a19 commit 2817dde

File tree

4 files changed

+161
-4
lines changed

4 files changed

+161
-4
lines changed

.github/workflows/build_wheels_windows.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,16 @@ jobs:
4343
cuda-version: ['12']
4444
include:
4545
# CUDA 12: Supports Maxwell (5.0) through Blackwell (10.0)
46+
# TODO(@Breakthrough): Expand PTX legacy support back to 5.0, it doesn't make the final
47+
# distribution that much larger and may help users with older GPUs.
4648
- cuda-version: '12'
4749
runs-on: 'windows-2025'
4850
cuda-installer: 'cuda_12.9.1_windows_network.exe'
4951
cuda-path-version: 'v12.9'
5052
cudnn-archive: 'cudnn-windows-x86_64-9.18.1.3_cuda12-archive.zip'
5153
cudnn-folder: 'cudnn-windows-x86_64-9.18.1.3_cuda12-archive'
54+
video-codec-sdk-archive: 'Video_Codec_SDK_13.0.37.zip'
55+
video-codec-sdk-folder: 'Video_Codec_SDK_13.0.37'
5256
cuda-arch-bin: '5.0;5.2;6.0;6.1;7.0;7.5;8.0;8.6;8.9;9.0;10.0'
5357
cuda-arch-ptx: '10.0'
5458
cache-key: 'nvidia-deps-cuda-12.9.1-cudnn-9.18.1.3'
@@ -60,6 +64,8 @@ jobs:
6064
# cuda-path-version: 'v13.1'
6165
# cudnn-archive: 'cudnn-windows-x86_64-9.18.1.3_cuda13-archive.zip'
6266
# cudnn-folder: 'cudnn-windows-x86_64-9.18.1.3_cuda13-archive'
67+
# video-codec-sdk-archive: 'Video_Codec_SDK_13.0.37.zip'
68+
# video-codec-sdk-folder: 'Video_Codec_SDK_13.0.37'
6369
# cuda-arch-bin: '7.5;8.0;8.6;8.9;9.0;10.0;12.0'
6470
# cuda-arch-ptx: '12.0'
6571
# cache-key: 'nvidia-deps-cuda-13.1.1-cudnn-9.18.1.3'
@@ -133,7 +139,20 @@ jobs:
133139
$CUDNN_PATH = "D:/a/opencv-python-cuda/opencv-python-cuda/${{ matrix.cudnn-folder }}"
134140
echo "CUDNN_LIBRARY=$CUDNN_PATH/lib/x64/cudnn.lib" | Out-File -FilePath $env:GITHUB_ENV -Append
135141
echo "CUDNN_INCLUDE_DIR=$CUDNN_PATH/include" | Out-File -FilePath $env:GITHUB_ENV -Append
136-
Copy-Item -Path "$CUDNN_PATH/bin/*" -Destination . -Include "*.dll"
142+
Copy-Item -Path "$CUDNN_PATH/bin/x64/*" -Destination . -Include "*.dll"
143+
shell: pwsh
144+
- name: 🔧 Install NVIDIA Video Codec SDK
145+
run: |
146+
$sdk_path = ".deps/Nvidia/${{ matrix.video-codec-sdk-archive }}"
147+
if (-not (Test-Path $sdk_path)) {
148+
throw "Video Codec SDK archive not found at $sdk_path"
149+
}
150+
echo "Installing Video Codec SDK..."
151+
7z x $sdk_path
152+
$SDK_PATH = "D:/a/opencv-python-cuda/opencv-python-cuda/${{ matrix.video-codec-sdk-folder }}"
153+
echo "CUDA_nvcuvid_LIBRARY=$SDK_PATH/Lib/win/x64/nvcuvid.lib" | Out-File -FilePath $env:GITHUB_ENV -Append
154+
echo "CUDA_nvencodeapi_LIBRARY=$SDK_PATH/Lib/win/x64/nvencodeapi.lib" | Out-File -FilePath $env:GITHUB_ENV -Append
155+
echo "NVCUVID_INCLUDE_DIR=$SDK_PATH/Interface" | Out-File -FilePath $env:GITHUB_ENV -Append
137156
shell: pwsh
138157

139158
- name: Restore build artifacts

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Download: [Latest Release (4.12.0-dev0)](https://github.com/Breakthrough/opencv-
44

55
## What is `opencv-python-cuda`?
66

7-
Pre-built NVIDIA® CUDA™ enabled OpenCV packages for Python that come with all batteries included. This is a fork of [the official opencv-python project](https://github.com/opencv/opencv-python). Right now packages are only produced for Windows x64, and devices must be Maxwell class (GeForce 900 series) or newer. Once installed via `pip` (or another Python package manager like `uv`), the following should *just work*:
7+
Pre-built NVIDIA® CUDA™ enabled OpenCV packages for Python that come with all batteries included. This is a fork of [the official opencv-python project](https://github.com/opencv/opencv-python). Right now packages are only produced for Windows x64, and devices must be Turing class (GeForce 2000 series) or newer. Once installed via `pip` (or another Python package manager like `uv`), the following should *just work*:
88

99
```
1010
import cv2

WORKFLOW.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Workflow Guide
2+
3+
## Repository Setup
4+
5+
### Cloning the Repository
6+
7+
```bash
8+
git clone https://github.com/Breakthrough/opencv-python-cuda.git
9+
cd opencv-python-cuda
10+
```
11+
12+
### Adding Upstream Remote
13+
14+
To sync with the main `opencv/opencv-python` repository, add it as a remote:
15+
16+
```bash
17+
git remote add upstream https://github.com/opencv/opencv-python.git
18+
```
19+
20+
### Preventing Tag Pollution
21+
22+
The upstream `opencv/opencv-python` repo has numeric tags (0, 1, 2, ... 90) that will pollute your local repo during fetches. To prevent this, configure the remote to exclude tags:
23+
24+
```bash
25+
git config remote.upstream.tagOpt --no-tags
26+
git config --add remote.upstream.fetch '^refs/tags/*'
27+
```
28+
29+
The `tagOpt` setting alone is sometimes not respected, so the negative refspec (`^refs/tags/*`) explicitly excludes all tags.
30+
31+
### Syncing with Upstream
32+
33+
After configuring the remote, you can sync without getting unwanted tags:
34+
35+
```bash
36+
git fetch upstream
37+
git pull --rebase upstream 4.x
38+
```
39+
40+
### Removing Accidentally Fetched Tags
41+
42+
If you already fetched the numeric tags, remove them with:
43+
44+
```bash
45+
git tag -d 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 68 70 72 74 76 78 80 82 84 86 88 90
46+
```
47+
48+
---
49+
50+
## Triggering Builds
51+
52+
To trigger the Windows CUDA build workflow:
53+
54+
```bash
55+
gh workflow run build_wheels_windows.yml --ref 4.x-cuda -R Breakthrough/opencv-python-cuda
56+
```
57+
58+
**Important:** Always specify `-R Breakthrough/opencv-python-cuda` when using `gh` commands. This repo is a fork of `opencv/opencv-python`, and `gh` will default to the parent repository without the explicit `-R` flag.
59+
60+
### Build Options
61+
62+
| Option | Description | Default |
63+
|--------|-------------|---------|
64+
| `restore_build_cache` | Restore build cache from previous runs | `true` |
65+
| `save_build_cache` | Save build cache after completion | `true` |
66+
| `rolling_build` | Use latest commit from upstream OpenCV | `false` |
67+
68+
Example with options:
69+
70+
```bash
71+
gh workflow run build_wheels_windows.yml --ref 4.x-cuda -R Breakthrough/opencv-python-cuda \
72+
-f restore_build_cache=false \
73+
-f save_build_cache=true
74+
```
75+
76+
### Force Rebuild (No Cache)
77+
78+
To force a complete rebuild without using cached artifacts:
79+
80+
```bash
81+
gh workflow run build_wheels_windows.yml --ref 4.x-cuda -R Breakthrough/opencv-python-cuda \
82+
-f restore_build_cache=false
83+
```
84+
85+
---
86+
87+
## Monitoring Builds
88+
89+
List recent runs:
90+
91+
```bash
92+
gh run list -R Breakthrough/opencv-python-cuda --limit 5
93+
```
94+
95+
Watch a running build:
96+
97+
```bash
98+
gh run watch <run-id> -R Breakthrough/opencv-python-cuda
99+
```
100+
101+
View build details:
102+
103+
```bash
104+
gh run view <run-id> -R Breakthrough/opencv-python-cuda
105+
```
106+
107+
---
108+
109+
## Reference: Git Config for Remotes
110+
111+
After setup, your `.git/config` remote sections should look like:
112+
113+
```ini
114+
[remote "origin"]
115+
url = https://github.com/Breakthrough/opencv-python-cuda.git
116+
fetch = +refs/heads/*:refs/remotes/origin/*
117+
118+
[remote "upstream"]
119+
url = https://github.com/opencv/opencv-python.git
120+
fetch = +refs/heads/*:refs/remotes/upstream/*
121+
fetch = ^refs/tags/*
122+
tagOpt = --no-tags
123+
```

setup.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ def main():
162162
cudnn_library = os.environ["CUDNN_LIBRARY"]
163163
cudnn_include_dir = os.environ["CUDNN_INCLUDE_DIR"]
164164

165+
# Video Codec SDK paths for NVCUVID/NVCUVENC (optional, enables hardware video decode/encode)
166+
nvcuvid_library = os.environ.get("CUDA_nvcuvid_LIBRARY", "")
167+
nvencodeapi_library = os.environ.get("CUDA_nvencodeapi_LIBRARY", "")
168+
nvcuvid_include_dir = os.environ.get("NVCUVID_INCLUDE_DIR", "")
169+
165170
cmake_args = (
166171
(ci_cmake_generator if is_CI_build else [])
167172
+ [
@@ -191,13 +196,23 @@ def main():
191196
"-DPYTHON3_LIMITED_API=ON",
192197
"-DBUILD_OPENEXR=ON",
193198
"-DWITH_CUDA=ON",
194-
# TODO(@Breakthrough): Download and install the required dependencies to enable this in build_wheels_windows.yml.
195-
"-DWITH_NVCUVID=OFF",
199+
"-DWITH_NVCUVID=ON",
200+
"-DWITH_NVCUVENC=ON",
196201
f"-DCUDA_ARCH_BIN={cuda_arch_bin}",
197202
f"-DCUDA_ARCH_PTX={cuda_arch_ptx}",
198203
f"-DCUDNN_LIBRARY={cudnn_library}",
199204
f"-DCUDNN_INCLUDE_DIR={cudnn_include_dir}",
200205
]
206+
+ (
207+
# Video Codec SDK paths for hardware video decode/encode support
208+
[
209+
f"-DCUDA_nvcuvid_LIBRARY={nvcuvid_library}",
210+
f"-DCUDA_nvencodeapi_LIBRARY={nvencodeapi_library}",
211+
f"-DCMAKE_INCLUDE_PATH={nvcuvid_include_dir}",
212+
]
213+
if nvcuvid_library and nvcuvid_include_dir
214+
else []
215+
)
201216
+ (
202217
# CUDA 12.9+ requires MSVC's conformant preprocessor for CCCL headers.
203218
# -Xcompiler passes the flag from nvcc to the host compiler (MSVC).

0 commit comments

Comments
 (0)