Skip to content

Commit 76d1f64

Browse files
NicolasHugscottsDan-FloresDaniel Florestraversaro
authored
Release 0.8.1 (#1000)
Co-authored-by: Scott Schneider <[email protected]> Co-authored-by: Dan-Flores <[email protected]> Co-authored-by: Daniel Flores <[email protected]> Co-authored-by: Silvio Traversaro <[email protected]> Co-authored-by: Molly Xu <[email protected]> Co-authored-by: Molly Xu <[email protected]> Co-authored-by: SuperKenVery <[email protected]>
1 parent e5b6680 commit 76d1f64

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2038
-784
lines changed

.github/workflows/linux_wheel.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,14 @@ jobs:
7272
name: meta-pytorch_torchcodec__${{ matrix.python-version }}_cpu_x86_64
7373
path: pytorch/torchcodec/dist/
7474
- name: Setup conda env
75-
uses: conda-incubator/setup-miniconda@v2
75+
uses: conda-incubator/setup-miniconda@v3
7676
with:
7777
auto-update-conda: true
78-
miniconda-version: "latest"
78+
# Using miniforge instead of miniconda ensures that the default
79+
# conda channel is conda-forge instead of main/default. This ensures
80+
# ABI consistency between dependencies:
81+
# https://conda-forge.org/docs/user/transitioning_from_defaults/
82+
miniforge-version: latest
7983
activate-environment: test
8084
python-version: ${{ matrix.python-version }}
8185
- name: Update pip

.github/workflows/reference_resources.yaml

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,51 @@ defaults:
1414
shell: bash -l -eo pipefail {0}
1515

1616
jobs:
17+
generate-matrix:
18+
uses: pytorch/test-infra/.github/workflows/generate_binary_build_matrix.yml@main
19+
with:
20+
package-type: wheel
21+
os: linux
22+
test-infra-repository: pytorch/test-infra
23+
test-infra-ref: main
24+
with-xpu: disable
25+
with-rocm: disable
26+
with-cuda: disable
27+
build-python-only: "disable"
28+
29+
build:
30+
needs: generate-matrix
31+
strategy:
32+
fail-fast: false
33+
name: Build and Upload Linux wheel
34+
uses: pytorch/test-infra/.github/workflows/build_wheels_linux.yml@main
35+
with:
36+
repository: meta-pytorch/torchcodec
37+
ref: ""
38+
test-infra-repository: pytorch/test-infra
39+
test-infra-ref: main
40+
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
41+
pre-script: packaging/pre_build_script.sh
42+
post-script: packaging/post_build_script.sh
43+
smoke-test-script: packaging/fake_smoke_test.py
44+
package-name: torchcodec
45+
trigger-event: ${{ github.event_name }}
46+
build-platform: "python-build-package"
47+
build-command: "BUILD_AGAINST_ALL_FFMPEG_FROM_S3=1 python -m build --wheel -vvv --no-isolation"
48+
1749
test-reference-resource-generation:
50+
needs: build
1851
runs-on: ubuntu-latest
1952
strategy:
2053
fail-fast: false
2154
matrix:
2255
python-version: ['3.10']
2356
ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1']
2457
steps:
58+
- uses: actions/download-artifact@v4
59+
with:
60+
name: meta-pytorch_torchcodec__${{ matrix.python-version }}_cpu_x86_64
61+
path: pytorch/torchcodec/dist/
2562
- name: Setup conda env
2663
uses: conda-incubator/setup-miniconda@v2
2764
with:
@@ -43,11 +80,16 @@ jobs:
4380
# Note that we're installing stable - this is for running a script where we're a normal PyTorch
4481
# user, not for building TorhCodec.
4582
python -m pip install torch --index-url https://download.pytorch.org/whl/cpu
46-
python -m pip install numpy pillow
83+
python -m pip install numpy pillow pytest
4784
85+
- name: Install torchcodec from the wheel
86+
run: |
87+
wheel_path=`find pytorch/torchcodec/dist -type f -name "*.whl"`
88+
echo Installing $wheel_path
89+
python -m pip install $wheel_path -vvv
4890
- name: Check out repo
4991
uses: actions/checkout@v3
5092

5193
- name: Run generation reference resources
5294
run: |
53-
python test/generate_reference_resources.py
95+
python -m test.generate_reference_resources

.github/workflows/windows_wheel.yaml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ jobs:
7171
# TODO: FFmpeg 5 on Windows segfaults in avcodec_open2() when passing
7272
# bad parameters.
7373
# See https://github.com/pytorch/torchcodec/pull/806
74-
# TODO: Support FFmpeg 8 on Windows
75-
ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1']
74+
ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1', '8.0']
7675
needs: build
7776
steps:
7877
- uses: actions/download-artifact@v4
@@ -83,7 +82,11 @@ jobs:
8382
uses: conda-incubator/setup-miniconda@v2
8483
with:
8584
auto-update-conda: true
86-
miniconda-version: "latest"
85+
# Using miniforge instead of miniconda ensures that the default
86+
# conda channel is conda-forge instead of main/default. This ensures
87+
# ABI consistency between dependencies:
88+
# https://conda-forge.org/docs/user/transitioning_from_defaults/
89+
miniforge-version: latest
8790
activate-environment: test
8891
python-version: ${{ matrix.python-version }}
8992
- name: Update pip

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ ffmpeg -f lavfi -i \
107107
`torch` and `torchcodec`.
108108

109109
2. Install FFmpeg, if it's not already installed. Linux distributions usually
110-
come with FFmpeg pre-installed. TorchCodec supports all major FFmpeg versions
111-
in [4, 7].
110+
come with FFmpeg pre-installed. TorchCodec supports major FFmpeg versions
111+
in [4, 7] on all platforms, and FFmpeg version 8 is supported on Mac and Linux.
112112

113113
If FFmpeg is not already installed, or you need a more recent version, an
114114
easy way to install it is to use `conda`:
@@ -131,6 +131,7 @@ The following table indicates the compatibility between versions of
131131
| `torchcodec` | `torch` | Python |
132132
| ------------------ | ------------------ | ------------------- |
133133
| `main` / `nightly` | `main` / `nightly` | `>=3.10`, `<=3.13` |
134+
| `0.8` | `2.9` | `>=3.10`, `<=3.13` |
134135
| `0.7` | `2.8` | `>=3.9`, `<=3.13` |
135136
| `0.6` | `2.8` | `>=3.9`, `<=3.13` |
136137
| `0.5` | `2.7` | `>=3.9`, `<=3.13` |
@@ -147,7 +148,8 @@ format you want. Refer to Nvidia's GPU support matrix for more details
147148
[here](https://developer.nvidia.com/video-encode-and-decode-gpu-support-matrix-new).
148149

149150
1. Install FFmpeg with NVDEC support.
150-
TorchCodec with CUDA should work with FFmpeg versions in [4, 7].
151+
TorchCodec with CUDA should work with FFmpeg versions in [4, 7] on all platforms,
152+
and FFmpeg version 8 is supported on Linux.
151153

152154
If FFmpeg is not already installed, or you need a more recent version, an
153155
easy way to install it is to use `conda`:
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import math
2+
from argparse import ArgumentParser
3+
from pathlib import Path
4+
from time import perf_counter_ns
5+
6+
import torch
7+
from torch import Tensor
8+
from torchcodec._core import add_video_stream, create_from_file, get_frames_by_pts
9+
from torchcodec.decoders import VideoDecoder
10+
from torchvision.transforms import v2
11+
12+
DEFAULT_NUM_EXP = 20
13+
14+
15+
def bench(f, *args, num_exp=DEFAULT_NUM_EXP, warmup=1) -> Tensor:
16+
17+
for _ in range(warmup):
18+
f(*args)
19+
20+
times = []
21+
for _ in range(num_exp):
22+
start = perf_counter_ns()
23+
f(*args)
24+
end = perf_counter_ns()
25+
times.append(end - start)
26+
return torch.tensor(times).float()
27+
28+
29+
def report_stats(times: Tensor, unit: str = "ms", prefix: str = "") -> float:
30+
mul = {
31+
"ns": 1,
32+
"µs": 1e-3,
33+
"ms": 1e-6,
34+
"s": 1e-9,
35+
}[unit]
36+
times = times * mul
37+
std = times.std().item()
38+
med = times.median().item()
39+
mean = times.mean().item()
40+
min = times.min().item()
41+
max = times.max().item()
42+
print(
43+
f"{prefix:<45} {med = :.2f}, {mean = :.2f} +- {std:.2f}, {min = :.2f}, {max = :.2f} - in {unit}"
44+
)
45+
46+
47+
def torchvision_resize(
48+
path: Path, pts_seconds: list[float], dims: tuple[int, int]
49+
) -> None:
50+
decoder = create_from_file(str(path), seek_mode="approximate")
51+
add_video_stream(decoder)
52+
raw_frames, *_ = get_frames_by_pts(decoder, timestamps=pts_seconds)
53+
return v2.functional.resize(raw_frames, size=dims)
54+
55+
56+
def torchvision_crop(
57+
path: Path, pts_seconds: list[float], dims: tuple[int, int], x: int, y: int
58+
) -> None:
59+
decoder = create_from_file(str(path), seek_mode="approximate")
60+
add_video_stream(decoder)
61+
raw_frames, *_ = get_frames_by_pts(decoder, timestamps=pts_seconds)
62+
return v2.functional.crop(raw_frames, top=y, left=x, height=dims[0], width=dims[1])
63+
64+
65+
def decoder_native_resize(
66+
path: Path, pts_seconds: list[float], dims: tuple[int, int]
67+
) -> None:
68+
decoder = create_from_file(str(path), seek_mode="approximate")
69+
add_video_stream(decoder, transform_specs=f"resize, {dims[0]}, {dims[1]}")
70+
return get_frames_by_pts(decoder, timestamps=pts_seconds)[0]
71+
72+
73+
def decoder_native_crop(
74+
path: Path, pts_seconds: list[float], dims: tuple[int, int], x: int, y: int
75+
) -> None:
76+
decoder = create_from_file(str(path), seek_mode="approximate")
77+
add_video_stream(decoder, transform_specs=f"crop, {dims[0]}, {dims[1]}, {x}, {y}")
78+
return get_frames_by_pts(decoder, timestamps=pts_seconds)[0]
79+
80+
81+
def main():
82+
parser = ArgumentParser()
83+
parser.add_argument("--path", type=str, help="path to file", required=True)
84+
parser.add_argument(
85+
"--num-exp",
86+
type=int,
87+
default=DEFAULT_NUM_EXP,
88+
help="number of runs to average over",
89+
)
90+
91+
args = parser.parse_args()
92+
path = Path(args.path)
93+
94+
metadata = VideoDecoder(path).metadata
95+
duration = metadata.duration_seconds
96+
97+
print(
98+
f"Benchmarking {path.name}, duration: {duration}, codec: {metadata.codec}, averaging over {args.num_exp} runs:"
99+
)
100+
101+
input_height = metadata.height
102+
input_width = metadata.width
103+
fraction_of_total_frames_to_sample = [0.005, 0.01, 0.05, 0.1]
104+
fraction_of_input_dimensions = [0.5, 0.25, 0.125]
105+
106+
for num_fraction in fraction_of_total_frames_to_sample:
107+
num_frames_to_sample = math.ceil(metadata.num_frames * num_fraction)
108+
print(
109+
f"Sampling {num_fraction * 100}%, {num_frames_to_sample}, of {metadata.num_frames} frames"
110+
)
111+
uniform_timestamps = [
112+
i * duration / num_frames_to_sample for i in range(num_frames_to_sample)
113+
]
114+
115+
for dims_fraction in fraction_of_input_dimensions:
116+
dims = (int(input_height * dims_fraction), int(input_width * dims_fraction))
117+
118+
times = bench(
119+
torchvision_resize, path, uniform_timestamps, dims, num_exp=args.num_exp
120+
)
121+
report_stats(times, prefix=f"torchvision_resize({dims})")
122+
123+
times = bench(
124+
decoder_native_resize,
125+
path,
126+
uniform_timestamps,
127+
dims,
128+
num_exp=args.num_exp,
129+
)
130+
report_stats(times, prefix=f"decoder_native_resize({dims})")
131+
print()
132+
133+
center_x = (input_height - dims[0]) // 2
134+
center_y = (input_width - dims[1]) // 2
135+
times = bench(
136+
torchvision_crop,
137+
path,
138+
uniform_timestamps,
139+
dims,
140+
center_x,
141+
center_y,
142+
num_exp=args.num_exp,
143+
)
144+
report_stats(
145+
times, prefix=f"torchvision_crop({dims}, {center_x}, {center_y})"
146+
)
147+
148+
times = bench(
149+
decoder_native_crop,
150+
path,
151+
uniform_timestamps,
152+
dims,
153+
center_x,
154+
center_y,
155+
num_exp=args.num_exp,
156+
)
157+
report_stats(
158+
times, prefix=f"decoder_native_crop({dims}, {center_x}, {center_y})"
159+
)
160+
print()
161+
162+
163+
if __name__ == "__main__":
164+
main()

docs/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ We achieve these capabilities through:
1111

1212
* Pythonic APIs that mirror Python and PyTorch conventions.
1313
* Relying on `FFmpeg <https://www.ffmpeg.org/>`_ to do the decoding / encoding.
14-
TorchCodec uses the version of FFmpeg you already have installed. FMPEG is a
14+
TorchCodec uses the version of FFmpeg you already have installed. FFmpeg is a
1515
mature library with broad coverage available on most systems. It is, however,
1616
not easy to use. TorchCodec abstracts FFmpeg's complexity to ensure it is
1717
used correctly and efficiently.

0 commit comments

Comments
 (0)