Skip to content

Commit b1c077f

Browse files
author
Dmitry Rogozhkin
committed
Expose TorchCodecConfig.cmake
This commit exposes torchcodec core library to be used by third party modules on the C++ level. The primary purpose is to allow non-CUDA device interfaces out-of-tree implementations. There are the following major changes: * Exposed TorchCodecConfig.cmake which defines torchcodec targets to be linked with * Provided Python level APIs to faciliate out-of-tree device interfaces work with torchcodec: * `torchcodec.cmake_prefix_path` - path which points to `TorchCodecConfig.cmake` configuration * `torchcodec.variant` - variant of the torchcodec library which was loaded, i.e. N in libtorchcodec_core{N}.so (currently ffmpeg_major_version) * `torchcodec.core_library_path` - full path of the loaded torchcodec core library * `src/torchcodec/_core/` dropped from include paths to allow using of the core library out-of-tree `TorchCodecConfig.cmake` has 2 working modes: * By default config works by checking available version of FFmpeg libraries via `pkg-config` and configures corresponding (single) version of torchcodec * Altenatively, if `TORCHCODEC_FFMPEG{N}_INSTALL_PREFIX` is set (`N=4,5,6,7` - version of FFmpeg), then config defines torchcodec target corresponding to the specified FFmpeg version. Note that multiple prefixes can be specified at the same time allowing to build against few torchcodec versions at once. Config will define `TORCHCODEC_VARIANTS` variable with value corresponding to FFmpeg major versions of available torchcodec core libraries. Further, config will also define `torchcodec::ffmpeg${N}` and `torchcodec::core${N}` targets where `N` takes values from `TORCHCODEC_VARIANTS`. Signed-off-by: Dmitry Rogozhkin <dmitry.v.rogozhkin@gmail.com>
1 parent f991110 commit b1c077f

File tree

4 files changed

+201
-1
lines changed

4 files changed

+201
-1
lines changed

src/torchcodec/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
# This source code is licensed under the BSD-style license found in the
55
# LICENSE file in the root directory of this source tree.
66

7+
import os.path as _osp
8+
79
# Note: usort wants to put Frame and FrameBatch after decoders and samplers,
810
# but that results in circular import.
11+
from ._core import core_library_path, variant
912
from ._frame import AudioSamples, Frame, FrameBatch # usort:skip # noqa
1013
from . import decoders, samplers # noqa
1114

@@ -14,3 +17,5 @@
1417
from .version import __version__ # noqa: F401
1518
except Exception:
1619
pass
20+
21+
cmake_prefix_path = _osp.join(_osp.dirname(__file__), "share", "cmake")

src/torchcodec/_core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
_test_frame_pts_equality,
2020
add_audio_stream,
2121
add_video_stream,
22+
core_library_path,
2223
create_from_bytes,
2324
create_from_file,
2425
create_from_file_like,
@@ -41,4 +42,5 @@
4142
get_next_frame,
4243
scan_all_streams_to_update_metadata,
4344
seek_to_pts,
45+
variant,
4446
)

src/torchcodec/_core/ops.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import io
88
import json
9+
import os
910
import warnings
1011
from types import ModuleType
1112
from typing import List, Optional, Tuple, Union
@@ -21,6 +22,8 @@
2122

2223
_pybind_ops: Optional[ModuleType] = None
2324

25+
variant = None
26+
core_library_path = None
2427

2528
def load_torchcodec_shared_libraries():
2629
# Successively try to load the shared libraries for each version of FFmpeg
@@ -47,14 +50,19 @@ def load_torchcodec_shared_libraries():
4750
custom_ops_library_name = f"libtorchcodec_custom_ops{ffmpeg_major_version}"
4851
pybind_ops_library_name = f"libtorchcodec_pybind_ops{ffmpeg_major_version}"
4952
try:
50-
torch.ops.load_library(_get_extension_path(decoder_library_name))
53+
decoder_library_path = _get_extension_path(decoder_library_name)
54+
torch.ops.load_library(decoder_library_path)
5155
torch.ops.load_library(_get_extension_path(custom_ops_library_name))
5256

5357
pybind_ops_library_path = _get_extension_path(pybind_ops_library_name)
5458
global _pybind_ops
5559
_pybind_ops = _load_pybind11_module(
5660
pybind_ops_module_name, pybind_ops_library_path
5761
)
62+
global variant
63+
global core_library_path
64+
variant = ffmpeg_major_version
65+
core_library_path = decoder_library_path
5866
return
5967
except Exception as e:
6068
# TODO: recording and reporting exceptions this way is OK for now as it's just for debugging,
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# FindTorchCodec
2+
# --------------
3+
#
4+
# Finds the TorchCodec library
5+
#
6+
# This will define the following variables:
7+
#
8+
# TORCHCODEC_FOUND -- True if the system has the TorchCodec library
9+
# TORCHCODEC_VARIANTS -- List of TorchCodec variants
10+
#
11+
# and the following imported targets:
12+
#
13+
# torchcodec::ffmpeg${N}
14+
# torchcodec::core${N}
15+
#
16+
# where N is a TorchCodec variant from TORCHCODEC_VARIANTS list.
17+
18+
include(FindPackageHandleStandardArgs)
19+
20+
# Assume we are in <install-prefix>/share/cmake/TorchCodec/TorchCodecConfig.cmake
21+
get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
22+
get_filename_component(TORCHCODEC_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
23+
24+
# Include directories.
25+
set(TORCHCODEC_INCLUDE_DIRS ${TORCHCODEC_INSTALL_PREFIX}/_core)
26+
set(TORCHCODEC_VARIANTS "")
27+
28+
function(add_ffmpeg_target ffmpeg_major_version libs)
29+
set(target "torchcodec::ffmpeg${ffmpeg_major_version}")
30+
set(prefix "TORCHCODEC_FFMPEG${ffmpeg_major_version}_INSTALL_PREFIX")
31+
if (NOT DEFINED ENV{${prefix}})
32+
message("Skipping ${target} as ${prefix} is not defined")
33+
return()
34+
endif()
35+
36+
set(prefix "$ENV{${prefix}}")
37+
set(incdir "${prefix}/include")
38+
if (UNIX AND NOT APPLE)
39+
set(libdir "${prefix}/lib")
40+
else()
41+
message("Skipping ${target} on non-Linux platform")
42+
return()
43+
endif()
44+
45+
set(lib_paths "")
46+
foreach(lib IN LISTS libs)
47+
find_library(_LIB_PATH "${lib}" PATHS "${libdir}" NO_DEFAULT_PATH)
48+
if (NOT _LIB_PATH)
49+
message("Skipping ${target} as ${lib} is missing")
50+
return()
51+
else()
52+
list(APPEND lib_paths "${_LIB_PATH}")
53+
endif()
54+
# Removing _LIB_PATH from cache otherwise it won't be updated
55+
# on the next call to find_library().
56+
unset(_LIB_PATH CACHE)
57+
endforeach()
58+
59+
message("Adding ${target} target")
60+
add_library(${target} SHARED IMPORTED)
61+
set_target_properties(${target} PROPERTIES
62+
INTERFACE_INCLUDE_DIRECTORIES ${incdir}
63+
IMPORTED_LOCATION ${lib_paths}
64+
)
65+
endfunction()
66+
67+
function(add_torchcodec_target ffmpeg_major_version)
68+
set(target torchcodec::core${ffmpeg_major_version})
69+
70+
if (NOT TARGET torchcodec::ffmpeg${ffmpeg_major_version})
71+
message("Skipping ${target} as torchcodec::ffmpeg${ffmpeg_major_version} is not defined")
72+
return()
73+
endif()
74+
75+
find_library(_LIB_PATH torchcodec_core${ffmpeg_major_version}
76+
PATHS "${TORCHCODEC_INSTALL_PREFIX}" NO_CACHE NO_DEFAULT_PATH)
77+
if (NOT _LIB_PATH)
78+
message("Skipping ${target} as torchcodec_core${ffmpeg_major_version} is missing")
79+
return()
80+
endif()
81+
82+
message("Adding ${target} target")
83+
add_library(${target} SHARED IMPORTED)
84+
add_dependencies(${target} torchcodec::ffmpeg${ffmpeg_major_version})
85+
set_target_properties(${target} PROPERTIES
86+
INTERFACE_INCLUDE_DIRECTORIES ${TORCHCODEC_INCLUDE_DIRS}
87+
IMPORTED_LOCATION ${_LIB_PATH}
88+
)
89+
# Removing _LIB_PATH from cache otherwise it won't be updated
90+
# on the next call to find_library().
91+
unset(_LIB_PATH CACHE)
92+
93+
list(APPEND TORCHCODEC_VARIANTS "${ffmpeg_major_version}")
94+
set(TORCHCODEC_VARIANTS "${TORCHCODEC_VARIANTS}" PARENT_SCOPE)
95+
endfunction()
96+
97+
if (DEFINED ENV{TORCHCODEC_FFMPEG4_INSTALL_PREFIX} OR
98+
DEFINED ENV{TORCHCODEC_FFMPEG5_INSTALL_PREFIX} OR
99+
DEFINED ENV{TORCHCODEC_FFMPEG6_INSTALL_PREFIX} OR
100+
DEFINED ENV{TORCHCODEC_FFMPEG7_INSTALL_PREFIX})
101+
if (UNIX AND NOT APPLE)
102+
set(f4_library_file_names
103+
libavutil.so.56
104+
libavcodec.so.58
105+
libavformat.so.58
106+
libavdevice.so.58
107+
libavfilter.so.7
108+
libswscale.so.5
109+
libswresample.so.3
110+
)
111+
set(f5_library_file_names
112+
libavutil.so.57
113+
libavcodec.so.59
114+
libavformat.so.59
115+
libavdevice.so.59
116+
libavfilter.so.8
117+
libswscale.so.6
118+
libswresample.so.4
119+
)
120+
set(f6_library_file_names
121+
libavutil.so.58
122+
libavcodec.so.60
123+
libavformat.so.60
124+
libavdevice.so.60
125+
libavfilter.so.9
126+
libswscale.so.7
127+
libswresample.so.4
128+
)
129+
set(f7_library_file_names
130+
libavutil.so.59
131+
libavcodec.so.61
132+
libavformat.so.61
133+
libavdevice.so.61
134+
libavfilter.so.10
135+
libswscale.so.8
136+
libswresample.so.5
137+
)
138+
endif()
139+
140+
add_ffmpeg_target(4 "${f4_library_file_names}")
141+
add_ffmpeg_target(5 "${f5_library_file_names}")
142+
add_ffmpeg_target(6 "${f6_library_file_names}")
143+
add_ffmpeg_target(7 "${f7_library_file_names}")
144+
145+
add_torchcodec_target(4)
146+
add_torchcodec_target(5)
147+
add_torchcodec_target(6)
148+
add_torchcodec_target(7)
149+
else()
150+
find_package(PkgConfig REQUIRED)
151+
pkg_check_modules(TORCHCODEC_LIBAV IMPORTED_TARGET
152+
libavdevice
153+
libavfilter
154+
libavformat
155+
libavcodec
156+
libavutil
157+
libswresample
158+
libswscale
159+
)
160+
161+
if (TARGET PkgConfig::TORCHCODEC_LIBAV)
162+
# Split libavcodec's version string by '.' and convert it to a list
163+
string(REPLACE "." ";" libavcodec_version_list ${TORCHCODEC_LIBAV_libavcodec_VERSION})
164+
# Get the first element of the list, which is the major version
165+
list(GET libavcodec_version_list 0 libavcodec_major_version)
166+
167+
if (${libavcodec_major_version} STREQUAL "58")
168+
set(ffmpeg_major_version "4")
169+
elseif (${libavcodec_major_version} STREQUAL "59")
170+
set(ffmpeg_major_version "5")
171+
elseif (${libavcodec_major_version} STREQUAL "60")
172+
set(ffmpeg_major_version "6")
173+
elseif (${libavcodec_major_version} STREQUAL "61")
174+
set(ffmpeg_major_version "7")
175+
endif()
176+
177+
if (libavcodec_major_version)
178+
message("Adding torchcodec::ffmpeg${ffmpeg_major_version} target")
179+
add_library(torchcodec::ffmpeg${ffmpeg_major_version} ALIAS PkgConfig::TORCHCODEC_LIBAV)
180+
add_torchcodec_target(${ffmpeg_major_version})
181+
endif()
182+
endif()
183+
endif()
184+
185+
find_package_handle_standard_args(TorchCodec DEFAULT_MSG TORCHCODEC_VARIANTS)

0 commit comments

Comments
 (0)