Skip to content

Commit d830af9

Browse files
scottsNicolasHug
andauthored
Add core support for decoding from Python file-like objects (#564)
Co-authored-by: Nicolas Hug <[email protected]>
1 parent 324b509 commit d830af9

28 files changed

+715
-215
lines changed

.github/workflows/cpp_tests.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ jobs:
3434
python-version: '3.12'
3535
- name: Update pip
3636
run: python -m pip install --upgrade pip
37-
- name: Install dependencies
37+
- name: Install torch dependencies
3838
run: |
3939
python -m pip install --pre torch --index-url https://download.pytorch.org/whl/nightly/cpu
40-
- name: Install ffmpeg and pkg-config
40+
- name: Install ffmpeg, pkg-config and pybind11
4141
run: |
42-
conda install "ffmpeg=${{ matrix.ffmpeg-version-for-tests }}" pkg-config -c conda-forge
42+
conda install "ffmpeg=${{ matrix.ffmpeg-version-for-tests }}" pkg-config pybind11 -c conda-forge
4343
ffmpeg -version
4444
- name: Build and run C++ tests
4545
run: |

.github/workflows/docs.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ jobs:
3838
test-infra-repository: pytorch/test-infra
3939
test-infra-ref: main
4040
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
41+
pre-script: packaging/pre_build_script.sh
4142
post-script: packaging/post_build_script.sh
4243
smoke-test-script: packaging/fake_smoke_test.py
4344
package-name: torchcodec

.github/workflows/lint.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ jobs:
6363
- name: Install dependencies and FFmpeg
6464
run: |
6565
python -m pip install --pre torch --index-url https://download.pytorch.org/whl/nightly/cpu
66-
conda install "ffmpeg=7.0.1" pkg-config -c conda-forge
66+
conda install "ffmpeg=7.0.1" pkg-config pybind11 -c conda-forge
6767
ffmpeg -version
6868
- name: Build and install torchcodec
6969
run: |

.github/workflows/linux_cuda_wheel.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
test-infra-repository: pytorch/test-infra
4949
test-infra-ref: main
5050
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
51+
pre-script: packaging/pre_build_script.sh
5152
post-script: packaging/post_build_script.sh
5253
smoke-test-script: packaging/fake_smoke_test.py
5354
package-name: torchcodec

.github/workflows/linux_wheel.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
test-infra-repository: pytorch/test-infra
5050
test-infra-ref: main
5151
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
52+
pre-script: packaging/pre_build_script.sh
5253
post-script: packaging/post_build_script.sh
5354
smoke-test-script: packaging/fake_smoke_test.py
5455
package-name: torchcodec

.github/workflows/macos_wheel.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
test-infra-repository: pytorch/test-infra
5050
test-infra-ref: main
5151
build-matrix: ${{ needs.generate-matrix.outputs.matrix }}
52+
pre-script: packaging/pre_build_script.sh
5253
post-script: packaging/post_build_script.sh
5354
smoke-test-script: packaging/fake_smoke_test.py
5455
runner-type: macos-m1-stable

CONTRIBUTING.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ test locally you will need the following dependencies:
2020
installation already.
2121
- cmake
2222
- pkg-config
23+
- pybind11
2324
- FFmpeg
2425
- PyTorch nightly
2526

@@ -29,7 +30,7 @@ Start by installing the **nightly** build of PyTorch following the
2930
Then, the easiest way to install the rest of the dependencies is to run:
3031

3132
```bash
32-
conda install cmake pkg-config ffmpeg -c conda-forge
33+
conda install cmake pkg-config pbyind11 ffmpeg -c conda-forge
3334
```
3435

3536
### Clone and build

packaging/pre_build_script.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/bin/bash
2+
3+
set -ex
4+
5+
# We need to install pybind11 because we need its CMake helpers in order to
6+
# compile correctly on Mac. Pybind11 is actually a C++ header-only library,
7+
# and PyTorch actually has it included. PyTorch, however, does not have the
8+
# CMake helpers.
9+
conda install -y pybind11 -c conda-forge

setup.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def run(self):
6868
super().run()
6969

7070
def build_extension(self, ext):
71-
"""Call our CMake build system to build libtorchcodec?.so"""
71+
"""Call our CMake build system to build libtorchcodec*.so"""
7272
# Setuptools was designed to build one extension (.so file) at a time,
7373
# calling this method for each Extension object. We're using a
7474
# CMake-based build where all our extensions are built together at once.
@@ -136,21 +136,27 @@ def copy_extensions_to_source(self):
136136
This is called by setuptools at the end of .run() during editable installs.
137137
"""
138138
self.get_finalized_command("build_py")
139-
extension = ""
139+
extensions = []
140140
if sys.platform == "linux":
141-
extension = "so"
141+
extensions = ["so"]
142142
elif sys.platform == "darwin":
143-
extension = "dylib"
143+
# Mac has BOTH .dylib and .so as library extensions. Short version
144+
# is that a .dylib is a shared library that can be both dynamically
145+
# loaded and depended on by other libraries; a .so can only be a
146+
# dynamically loaded module. For more, see:
147+
# https://stackoverflow.com/a/2339910
148+
extensions = ["dylib", "so"]
144149
else:
145150
raise NotImplementedError(
146151
"Platforms other than linux/darwin are not supported yet"
147152
)
148153

149-
for so_file in self._install_prefix.glob(f"*.{extension}"):
150-
assert "libtorchcodec" in so_file.name
151-
destination = Path("src/torchcodec/") / so_file.name
152-
print(f"Copying {so_file} to {destination}")
153-
self.copy_file(so_file, destination, level=self.verbose)
154+
for ext in extensions:
155+
for lib_file in self._install_prefix.glob(f"*.{ext}"):
156+
assert "libtorchcodec" in lib_file.name
157+
destination = Path("src/torchcodec/") / lib_file.name
158+
print(f"Copying {lib_file} to {destination}")
159+
self.copy_file(lib_file, destination, level=self.verbose)
154160

155161

156162
NOT_A_LICENSE_VIOLATION_VAR = "I_CONFIRM_THIS_IS_NOT_A_LICENSE_VIOLATION"

src/torchcodec/_internally_replaced_utils.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
import importlib
88
import sys
99
from pathlib import Path
10+
from types import ModuleType
1011

1112

1213
# Copy pasted from torchvision
1314
# https://github.com/pytorch/vision/blob/947ae1dc71867f28021d5bc0ff3a19c249236e2a/torchvision/_internally_replaced_utils.py#L25
14-
def _get_extension_path(lib_name):
15+
def _get_extension_path(lib_name: str) -> str:
1516
extension_suffixes = []
1617
if sys.platform == "linux":
1718
extension_suffixes = importlib.machinery.EXTENSION_SUFFIXES
@@ -31,6 +32,22 @@ def _get_extension_path(lib_name):
3132
)
3233
ext_specs = extfinder.find_spec(lib_name)
3334
if ext_specs is None:
34-
raise ImportError
35+
raise ImportError(f"No spec found for {lib_name}")
36+
37+
if ext_specs.origin is None:
38+
raise ImportError(f"Existing spec found for {lib_name} does not have an origin")
3539

3640
return ext_specs.origin
41+
42+
43+
def _load_pybind11_module(module_name: str, library_path: str) -> ModuleType:
44+
spec = importlib.util.spec_from_file_location(
45+
module_name,
46+
library_path,
47+
)
48+
if spec is None:
49+
raise ImportError(
50+
f"Unable to load spec for module {module_name} from path {library_path}"
51+
)
52+
53+
return importlib.util.module_from_spec(spec)

0 commit comments

Comments
 (0)