Files
TheRock/rocm-systems/projects/rocdecode/samples/videoDecodeRGB/README.md
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

123 lines
4.6 KiB
Markdown

# Video decode RGB sample
This sample demonstrates decoding and optionally color-converting using the FFMpeg demuxer, the rocDecode API, and custom HIP kernels.
The FFmpeg demuxer is used to get individual frames that are then decoded using rocDecode API and optionally color-converted using custom HIP kernels on AMD hardware.
Decoded YUV output is converted to either RGB or BGR formats (24bit, 32bit, 48bit, 64bit) in separate threads so that both the VCN hardware and the compute engine can run in parallel.
HIP kernels are used for color conversion. After the frame has been decoded, the `ColorSpaceConversionThread` is notified and is used for post-processing.
## Prerequisites:
* Install [rocDecode](https://rocm.docs.amd.com/projects/rocDecode/en/latest/install/rocDecode-build-and-install.html)
* [FFMPEG](https://ffmpeg.org/about.html)
```shell
sudo apt install libavcodec-dev libavformat-dev libavutil-dev
```
## Build
```shell
mkdir video_decode_rgb_sample && cd video_decode_rgb_sample
cmake ../
make -j
```
## Run
```shell
./videodecodergb -i <input video file> [options]
```
### Options
| Flag | Argument | Description | Default |
|------|----------|-------------|---------|
| `-i` | `<path>` | Input video file path (required) | |
| `-o` | `<path>` | Output file path for decoded frames | (no output) |
| `-d` | `<id>` | GPU device ID | `0` |
| `-of` | `<format>` | Output format: `native`, `bgr`, `bgr48`, `rgb`, `rgb48`, `bgra`, `bgra64`, `rgba`, `rgba64` | `native` |
| `-cs` | `<standard>` | Color standard: `bt709`, `fcc`, `bt470`, `bt601`, `smpte240m`, `bt2020`, `bt2020c` | `bt709` |
| `-resize` | `<W>x<H>` | Resize output (width and height must be even values) | (no resize) |
| `-crop` | `<l,t,r,b>` | Crop rectangle (width and height must be even values) | (no crop) |
| `-disp_delay` | `<n>` | Number of frames to delay before display | `1` |
| `-f` | `<n>` | Number of frames to decode (`0` = entire stream) | `0` |
### Color conversion
The YUV to RGB conversion is performed on the GPU using HIP kernels defined in `utils/colorspace_kernels.cpp`. The conversion applies the standard-specific luma weights and studio-range scaling:
- **Luma (Y)** range: 16-235 (8-bit) or 64-940 (10-bit), scaled by `max / (white - black)`
- **Chroma (Cb/Cr)** range: 16-240 (8-bit) or 64-960 (10-bit), scaled by `max / (white_c - black)`
The following color standards are supported, each defining different luma weight coefficients (Kr, Kb):
| Standard | Kr | Kb |
|----------|------|------|
| BT.709 | 0.2126 | 0.0722 |
| FCC | 0.30 | 0.11 |
| BT.470 | 0.2990 | 0.1140 |
| BT.601 | 0.2990 | 0.1140 |
| SMPTE 240M | 0.212 | 0.087 |
| BT.2020 | 0.2627 | 0.0593 |
#### YUV to RGB formula (studio range)
Given a YUV pixel with studio-range values, the conversion to full-range RGB is:
```
Kg = 1 - Kr - Kb
fy = Y - low (low = 16 for 8-bit, 64<<6 for 10-bit P016)
fu = Cb - mid (mid = 128 for 8-bit, 1<<15 for 10-bit P016)
fv = Cr - mid
Base matrix (unscaled):
| 1 0 (1-Kr)/0.5 |
base = | 1 -Kb*(1-Kb) / (0.5*(1-Kb-Kr)) -Kr*(1-Kr) / (0.5*(1-Kb-Kr)) |
| 1 (1-Kb)/0.5 0 |
Column-wise scaling (luma and chroma scaled independently):
Sy = max / (white - black) luma scale
Sc = max / (white_c - black) chroma scale
mat[i][0] = base[i][0] * Sy for i = 0..2
mat[i][1] = base[i][1] * Sc for i = 0..2
mat[i][2] = base[i][2] * Sc for i = 0..2
Conversion:
R = mat[0][0]*fy + mat[0][1]*fu + mat[0][2]*fv
G = mat[1][0]*fy + mat[1][1]*fu + mat[1][2]*fv
B = mat[2][0]*fy + mat[2][1]*fu + mat[2][2]*fv
R, G, B = clamp(R, G, B, 0, maxf)
where maxf is the full storage range for the YUV unit type
(255 for 8-bit, 65535 for 16-bit P016).
```
### Validation with FFmpeg
A test script is provided to validate the GPU color conversion against FFmpeg's CPU-based conversion:
```shell
python3 test/testScripts/run_rocDecode_colorConvert.py \
--rocdecode_exe ./videodecodergb \
--input_file input.mp4 \
--num_frames 3 \
--tolerance 2
```
The script decodes frames with both `videodecodergb` and `ffmpeg` using each color standard, then compares the raw RGB output pixel-by-pixel. A per-channel tolerance (default ±2) accounts for floating-point rounding differences between GPU and CPU implementations.
The script automatically filters standards by bit depth:
- **8-bit streams**: tests bt709, fcc, bt470, bt601, smpte240m (skips bt2020/bt2020c)
- **10-bit streams**: tests bt2020, bt2020c (skips 8-bit standards)
See `test/testScripts/run_rocDecode_colorConvert.py --help` for all options.