From 949803ea29c99e0743378930757e67ac80bd8a6f Mon Sep 17 00:00:00 2001 From: Dmitry Rogozhkin Date: Fri, 3 Oct 2025 11:15:54 -0700 Subject: [PATCH] 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 --- src/torchcodec/__init__.py | 5 + src/torchcodec/_core/AVIOContextHolder.cpp | 2 +- src/torchcodec/_core/AVIOContextHolder.h | 2 +- src/torchcodec/_core/AVIOFileLikeContext.cpp | 2 +- src/torchcodec/_core/AVIOFileLikeContext.h | 2 +- src/torchcodec/_core/AVIOTensorContext.cpp | 2 +- src/torchcodec/_core/AVIOTensorContext.h | 2 +- .../_core/BetaCudaDeviceInterface.h | 14 +- src/torchcodec/_core/CUDACommon.h | 6 +- src/torchcodec/_core/CpuDeviceInterface.cpp | 2 +- src/torchcodec/_core/CpuDeviceInterface.h | 6 +- src/torchcodec/_core/CudaDeviceInterface.cpp | 6 +- src/torchcodec/_core/CudaDeviceInterface.h | 6 +- src/torchcodec/_core/DeviceInterface.cpp | 2 +- src/torchcodec/_core/DeviceInterface.h | 6 +- src/torchcodec/_core/Encoder.cpp | 4 +- src/torchcodec/_core/Encoder.h | 6 +- src/torchcodec/_core/FFMPEGCommon.cpp | 2 +- src/torchcodec/_core/FilterGraph.cpp | 2 +- src/torchcodec/_core/FilterGraph.h | 4 +- src/torchcodec/_core/Frame.cpp | 2 +- src/torchcodec/_core/Frame.h | 6 +- src/torchcodec/_core/NVDECCache.h | 4 +- src/torchcodec/_core/SingleStreamDecoder.cpp | 2 +- src/torchcodec/_core/SingleStreamDecoder.h | 12 +- src/torchcodec/_core/Transform.h | 2 +- src/torchcodec/_core/ValidationUtils.cpp | 2 +- src/torchcodec/_core/__init__.py | 2 + src/torchcodec/_core/custom_ops.cpp | 10 +- src/torchcodec/_core/ops.py | 10 +- src/torchcodec/_core/pybind_ops.cpp | 2 +- .../cmake/TorchCodec/TorchCodecConfig.cmake | 185 ++++++++++++++++++ 32 files changed, 261 insertions(+), 61 deletions(-) create mode 100644 src/torchcodec/share/cmake/TorchCodec/TorchCodecConfig.cmake diff --git a/src/torchcodec/__init__.py b/src/torchcodec/__init__.py index 2b6c9fb3e..b3ee534ab 100644 --- a/src/torchcodec/__init__.py +++ b/src/torchcodec/__init__.py @@ -4,8 +4,11 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. +import os.path as _osp + # Note: usort wants to put Frame and FrameBatch after decoders and samplers, # but that results in circular import. +from ._core import core_library_path, variant from ._frame import AudioSamples, Frame, FrameBatch # usort:skip # noqa from . import decoders, samplers # noqa @@ -14,3 +17,5 @@ from .version import __version__ # noqa: F401 except Exception: pass + +cmake_prefix_path = _osp.join(_osp.dirname(__file__), "share", "cmake") diff --git a/src/torchcodec/_core/AVIOContextHolder.cpp b/src/torchcodec/_core/AVIOContextHolder.cpp index c1188e684..73d18b4e0 100644 --- a/src/torchcodec/_core/AVIOContextHolder.cpp +++ b/src/torchcodec/_core/AVIOContextHolder.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/AVIOContextHolder.h" +#include "AVIOContextHolder.h" #include namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/AVIOContextHolder.h b/src/torchcodec/_core/AVIOContextHolder.h index 16d70beaf..7b1123e6d 100644 --- a/src/torchcodec/_core/AVIOContextHolder.h +++ b/src/torchcodec/_core/AVIOContextHolder.h @@ -6,7 +6,7 @@ #pragma once -#include "src/torchcodec/_core/FFMPEGCommon.h" +#include "FFMPEGCommon.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/AVIOFileLikeContext.cpp b/src/torchcodec/_core/AVIOFileLikeContext.cpp index 210942b57..a2cdad25b 100644 --- a/src/torchcodec/_core/AVIOFileLikeContext.cpp +++ b/src/torchcodec/_core/AVIOFileLikeContext.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/AVIOFileLikeContext.h" +#include "AVIOFileLikeContext.h" #include namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/AVIOFileLikeContext.h b/src/torchcodec/_core/AVIOFileLikeContext.h index fd7f534f3..001cda550 100644 --- a/src/torchcodec/_core/AVIOFileLikeContext.h +++ b/src/torchcodec/_core/AVIOFileLikeContext.h @@ -9,7 +9,7 @@ #include #include -#include "src/torchcodec/_core/AVIOContextHolder.h" +#include "AVIOContextHolder.h" namespace py = pybind11; diff --git a/src/torchcodec/_core/AVIOTensorContext.cpp b/src/torchcodec/_core/AVIOTensorContext.cpp index 3f45f5be5..0a80772a8 100644 --- a/src/torchcodec/_core/AVIOTensorContext.cpp +++ b/src/torchcodec/_core/AVIOTensorContext.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/AVIOTensorContext.h" +#include "AVIOTensorContext.h" #include namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/AVIOTensorContext.h b/src/torchcodec/_core/AVIOTensorContext.h index 15f97da55..ab6f52361 100644 --- a/src/torchcodec/_core/AVIOTensorContext.h +++ b/src/torchcodec/_core/AVIOTensorContext.h @@ -7,7 +7,7 @@ #pragma once #include -#include "src/torchcodec/_core/AVIOContextHolder.h" +#include "AVIOContextHolder.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/BetaCudaDeviceInterface.h b/src/torchcodec/_core/BetaCudaDeviceInterface.h index 0bf9951d6..a0fb30b54 100644 --- a/src/torchcodec/_core/BetaCudaDeviceInterface.h +++ b/src/torchcodec/_core/BetaCudaDeviceInterface.h @@ -15,11 +15,11 @@ #pragma once -#include "src/torchcodec/_core/CUDACommon.h" -#include "src/torchcodec/_core/Cache.h" -#include "src/torchcodec/_core/DeviceInterface.h" -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/NVDECCache.h" +#include "CUDACommon.h" +#include "Cache.h" +#include "DeviceInterface.h" +#include "FFMPEGCommon.h" +#include "NVDECCache.h" #include #include @@ -28,8 +28,8 @@ #include #include -#include "src/torchcodec/_core/nvcuvid_include/cuviddec.h" -#include "src/torchcodec/_core/nvcuvid_include/nvcuvid.h" +#include "nvcuvid_include/cuviddec.h" +#include "nvcuvid_include/nvcuvid.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/CUDACommon.h b/src/torchcodec/_core/CUDACommon.h index b4c081885..cd5ebf1e9 100644 --- a/src/torchcodec/_core/CUDACommon.h +++ b/src/torchcodec/_core/CUDACommon.h @@ -11,9 +11,9 @@ #include #include -#include "src/torchcodec/_core/Cache.h" -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/Frame.h" +#include "Cache.h" +#include "FFMPEGCommon.h" +#include "Frame.h" extern "C" { #include diff --git a/src/torchcodec/_core/CpuDeviceInterface.cpp b/src/torchcodec/_core/CpuDeviceInterface.cpp index e6b96e3e4..fde48b1d6 100644 --- a/src/torchcodec/_core/CpuDeviceInterface.cpp +++ b/src/torchcodec/_core/CpuDeviceInterface.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/CpuDeviceInterface.h" +#include "CpuDeviceInterface.h" namespace facebook::torchcodec { namespace { diff --git a/src/torchcodec/_core/CpuDeviceInterface.h b/src/torchcodec/_core/CpuDeviceInterface.h index 399b0c6be..95711fd4c 100644 --- a/src/torchcodec/_core/CpuDeviceInterface.h +++ b/src/torchcodec/_core/CpuDeviceInterface.h @@ -6,9 +6,9 @@ #pragma once -#include "src/torchcodec/_core/DeviceInterface.h" -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/FilterGraph.h" +#include "DeviceInterface.h" +#include "FFMPEGCommon.h" +#include "FilterGraph.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/CudaDeviceInterface.cpp b/src/torchcodec/_core/CudaDeviceInterface.cpp index e8df0a608..cafbd2f42 100644 --- a/src/torchcodec/_core/CudaDeviceInterface.cpp +++ b/src/torchcodec/_core/CudaDeviceInterface.cpp @@ -3,9 +3,9 @@ #include #include -#include "src/torchcodec/_core/Cache.h" -#include "src/torchcodec/_core/CudaDeviceInterface.h" -#include "src/torchcodec/_core/FFMPEGCommon.h" +#include "Cache.h" +#include "CudaDeviceInterface.h" +#include "FFMPEGCommon.h" extern "C" { #include diff --git a/src/torchcodec/_core/CudaDeviceInterface.h b/src/torchcodec/_core/CudaDeviceInterface.h index 8f2ca76cc..102b1d044 100644 --- a/src/torchcodec/_core/CudaDeviceInterface.h +++ b/src/torchcodec/_core/CudaDeviceInterface.h @@ -6,9 +6,9 @@ #pragma once -#include "src/torchcodec/_core/CUDACommon.h" -#include "src/torchcodec/_core/DeviceInterface.h" -#include "src/torchcodec/_core/FilterGraph.h" +#include "CUDACommon.h" +#include "DeviceInterface.h" +#include "FilterGraph.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/DeviceInterface.cpp b/src/torchcodec/_core/DeviceInterface.cpp index 2f910e998..a41fb3477 100644 --- a/src/torchcodec/_core/DeviceInterface.cpp +++ b/src/torchcodec/_core/DeviceInterface.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/DeviceInterface.h" +#include "DeviceInterface.h" #include #include diff --git a/src/torchcodec/_core/DeviceInterface.h b/src/torchcodec/_core/DeviceInterface.h index 35984da26..93b591bdd 100644 --- a/src/torchcodec/_core/DeviceInterface.h +++ b/src/torchcodec/_core/DeviceInterface.h @@ -12,9 +12,9 @@ #include #include #include "FFMPEGCommon.h" -#include "src/torchcodec/_core/Frame.h" -#include "src/torchcodec/_core/StreamOptions.h" -#include "src/torchcodec/_core/Transform.h" +#include "Frame.h" +#include "StreamOptions.h" +#include "Transform.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/Encoder.cpp b/src/torchcodec/_core/Encoder.cpp index 9a1f4ee87..8ce41a673 100644 --- a/src/torchcodec/_core/Encoder.cpp +++ b/src/torchcodec/_core/Encoder.cpp @@ -1,7 +1,7 @@ #include -#include "src/torchcodec/_core/AVIOTensorContext.h" -#include "src/torchcodec/_core/Encoder.h" +#include "AVIOTensorContext.h" +#include "Encoder.h" #include "torch/types.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/Encoder.h b/src/torchcodec/_core/Encoder.h index 81d8d1975..6d5da2864 100644 --- a/src/torchcodec/_core/Encoder.h +++ b/src/torchcodec/_core/Encoder.h @@ -1,8 +1,8 @@ #pragma once #include -#include "src/torchcodec/_core/AVIOContextHolder.h" -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/StreamOptions.h" +#include "AVIOContextHolder.h" +#include "FFMPEGCommon.h" +#include "StreamOptions.h" namespace facebook::torchcodec { class AudioEncoder { diff --git a/src/torchcodec/_core/FFMPEGCommon.cpp b/src/torchcodec/_core/FFMPEGCommon.cpp index 94c666d79..17b0672bf 100644 --- a/src/torchcodec/_core/FFMPEGCommon.cpp +++ b/src/torchcodec/_core/FFMPEGCommon.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/FFMPEGCommon.h" +#include "FFMPEGCommon.h" #include diff --git a/src/torchcodec/_core/FilterGraph.cpp b/src/torchcodec/_core/FilterGraph.cpp index 70bc2b5dd..327a16aad 100644 --- a/src/torchcodec/_core/FilterGraph.cpp +++ b/src/torchcodec/_core/FilterGraph.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/FilterGraph.h" +#include "FilterGraph.h" extern "C" { #include diff --git a/src/torchcodec/_core/FilterGraph.h b/src/torchcodec/_core/FilterGraph.h index 8cba571bd..12475fe47 100644 --- a/src/torchcodec/_core/FilterGraph.h +++ b/src/torchcodec/_core/FilterGraph.h @@ -6,8 +6,8 @@ #pragma once -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/StreamOptions.h" +#include "FFMPEGCommon.h" +#include "StreamOptions.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/Frame.cpp b/src/torchcodec/_core/Frame.cpp index 9fa87a1cb..217b5c68e 100644 --- a/src/torchcodec/_core/Frame.cpp +++ b/src/torchcodec/_core/Frame.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/Frame.h" +#include "Frame.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/Frame.h b/src/torchcodec/_core/Frame.h index 4b27d5bdd..e17964423 100644 --- a/src/torchcodec/_core/Frame.h +++ b/src/torchcodec/_core/Frame.h @@ -7,9 +7,9 @@ #pragma once #include -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/Metadata.h" -#include "src/torchcodec/_core/StreamOptions.h" +#include "FFMPEGCommon.h" +#include "Metadata.h" +#include "StreamOptions.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/NVDECCache.h b/src/torchcodec/_core/NVDECCache.h index 17fc99902..4d61c3f39 100644 --- a/src/torchcodec/_core/NVDECCache.h +++ b/src/torchcodec/_core/NVDECCache.h @@ -11,8 +11,8 @@ #include #include -#include "src/torchcodec/_core/nvcuvid_include/cuviddec.h" -#include "src/torchcodec/_core/nvcuvid_include/nvcuvid.h" +#include "nvcuvid_include/cuviddec.h" +#include "nvcuvid_include/nvcuvid.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/SingleStreamDecoder.cpp b/src/torchcodec/_core/SingleStreamDecoder.cpp index d06c47922..37630ee53 100644 --- a/src/torchcodec/_core/SingleStreamDecoder.cpp +++ b/src/torchcodec/_core/SingleStreamDecoder.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/SingleStreamDecoder.h" +#include "SingleStreamDecoder.h" #include #include #include diff --git a/src/torchcodec/_core/SingleStreamDecoder.h b/src/torchcodec/_core/SingleStreamDecoder.h index 48821ff09..faf5b1c1e 100644 --- a/src/torchcodec/_core/SingleStreamDecoder.h +++ b/src/torchcodec/_core/SingleStreamDecoder.h @@ -12,12 +12,12 @@ #include #include -#include "src/torchcodec/_core/AVIOContextHolder.h" -#include "src/torchcodec/_core/DeviceInterface.h" -#include "src/torchcodec/_core/FFMPEGCommon.h" -#include "src/torchcodec/_core/Frame.h" -#include "src/torchcodec/_core/StreamOptions.h" -#include "src/torchcodec/_core/Transform.h" +#include "AVIOContextHolder.h" +#include "DeviceInterface.h" +#include "FFMPEGCommon.h" +#include "Frame.h" +#include "StreamOptions.h" +#include "Transform.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/Transform.h b/src/torchcodec/_core/Transform.h index 6aea255ab..c583ef70a 100644 --- a/src/torchcodec/_core/Transform.h +++ b/src/torchcodec/_core/Transform.h @@ -8,7 +8,7 @@ #include #include -#include "src/torchcodec/_core/Frame.h" +#include "Frame.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/ValidationUtils.cpp b/src/torchcodec/_core/ValidationUtils.cpp index fae3dd940..da8262b83 100644 --- a/src/torchcodec/_core/ValidationUtils.cpp +++ b/src/torchcodec/_core/ValidationUtils.cpp @@ -4,7 +4,7 @@ // This source code is licensed under the BSD-style license found in the // LICENSE file in the root directory of this source tree. -#include "src/torchcodec/_core/ValidationUtils.h" +#include "ValidationUtils.h" #include #include "c10/util/Exception.h" diff --git a/src/torchcodec/_core/__init__.py b/src/torchcodec/_core/__init__.py index 24e54af0e..ea697f685 100644 --- a/src/torchcodec/_core/__init__.py +++ b/src/torchcodec/_core/__init__.py @@ -18,6 +18,7 @@ _test_frame_pts_equality, add_audio_stream, add_video_stream, + core_library_path, create_from_bytes, create_from_file, create_from_file_like, @@ -38,4 +39,5 @@ get_next_frame, scan_all_streams_to_update_metadata, seek_to_pts, + variant, ) diff --git a/src/torchcodec/_core/custom_ops.cpp b/src/torchcodec/_core/custom_ops.cpp index 7010c436a..77f4e80e5 100644 --- a/src/torchcodec/_core/custom_ops.cpp +++ b/src/torchcodec/_core/custom_ops.cpp @@ -10,11 +10,11 @@ #include #include "c10/core/SymIntArrayRef.h" #include "c10/util/Exception.h" -#include "src/torchcodec/_core/AVIOFileLikeContext.h" -#include "src/torchcodec/_core/AVIOTensorContext.h" -#include "src/torchcodec/_core/Encoder.h" -#include "src/torchcodec/_core/SingleStreamDecoder.h" -#include "src/torchcodec/_core/ValidationUtils.h" +#include "AVIOFileLikeContext.h" +#include "AVIOTensorContext.h" +#include "Encoder.h" +#include "SingleStreamDecoder.h" +#include "ValidationUtils.h" namespace facebook::torchcodec { diff --git a/src/torchcodec/_core/ops.py b/src/torchcodec/_core/ops.py index 64298eab5..c441d6c3f 100644 --- a/src/torchcodec/_core/ops.py +++ b/src/torchcodec/_core/ops.py @@ -6,6 +6,7 @@ import io import json +import os import warnings from types import ModuleType from typing import List, Optional, Tuple, Union @@ -21,6 +22,8 @@ _pybind_ops: Optional[ModuleType] = None +variant = None +core_library_path = None def load_torchcodec_shared_libraries(): # Successively try to load the shared libraries for each version of FFmpeg @@ -47,7 +50,8 @@ def load_torchcodec_shared_libraries(): custom_ops_library_name = f"libtorchcodec_custom_ops{ffmpeg_major_version}" pybind_ops_library_name = f"libtorchcodec_pybind_ops{ffmpeg_major_version}" try: - torch.ops.load_library(_get_extension_path(decoder_library_name)) + decoder_library_path = _get_extension_path(decoder_library_name) + torch.ops.load_library(decoder_library_path) torch.ops.load_library(_get_extension_path(custom_ops_library_name)) pybind_ops_library_path = _get_extension_path(pybind_ops_library_name) @@ -55,6 +59,10 @@ def load_torchcodec_shared_libraries(): _pybind_ops = _load_pybind11_module( pybind_ops_module_name, pybind_ops_library_path ) + global variant + global core_library_path + variant = ffmpeg_major_version + core_library_path = decoder_library_path return except Exception as e: # TODO: recording and reporting exceptions this way is OK for now as it's just for debugging, diff --git a/src/torchcodec/_core/pybind_ops.cpp b/src/torchcodec/_core/pybind_ops.cpp index f9cfd7eb6..1f2e792ee 100644 --- a/src/torchcodec/_core/pybind_ops.cpp +++ b/src/torchcodec/_core/pybind_ops.cpp @@ -8,7 +8,7 @@ #include #include -#include "src/torchcodec/_core/AVIOFileLikeContext.h" +#include "AVIOFileLikeContext.h" namespace py = pybind11; diff --git a/src/torchcodec/share/cmake/TorchCodec/TorchCodecConfig.cmake b/src/torchcodec/share/cmake/TorchCodec/TorchCodecConfig.cmake new file mode 100644 index 000000000..33471e002 --- /dev/null +++ b/src/torchcodec/share/cmake/TorchCodec/TorchCodecConfig.cmake @@ -0,0 +1,185 @@ +# FindTorchCodec +# -------------- +# +# Finds the TorchCodec library +# +# This will define the following variables: +# +# TORCHCODEC_FOUND -- True if the system has the TorchCodec library +# TORCHCODEC_VARIANTS -- List of TorchCodec variants +# +# and the following imported targets: +# +# torchcodec::ffmpeg${N} +# torchcodec::core${N} +# +# where N is a TorchCodec variant from TORCHCODEC_VARIANTS list. + +include(FindPackageHandleStandardArgs) + +# Assume we are in /share/cmake/TorchCodec/TorchCodecConfig.cmake +get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(TORCHCODEC_INSTALL_PREFIX "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) + +# Include directories. +set(TORCHCODEC_INCLUDE_DIRS ${TORCHCODEC_INSTALL_PREFIX}/_core) +set(TORCHCODEC_VARIANTS "") + +function(add_ffmpeg_target ffmpeg_major_version libs) + set(target "torchcodec::ffmpeg${ffmpeg_major_version}") + set(prefix "TORCHCODEC_FFMPEG${ffmpeg_major_version}_INSTALL_PREFIX") + if (NOT DEFINED ENV{${prefix}}) + message("Skipping ${target} as ${prefix} is not defined") + return() + endif() + + set(prefix "$ENV{${prefix}}") + set(incdir "${prefix}/include") + if (UNIX AND NOT APPLE) + set(libdir "${prefix}/lib") + else() + message("Skipping ${target} on non-Linux platform") + return() + endif() + + set(lib_paths "") + foreach(lib IN LISTS libs) + find_library(_LIB_PATH "${lib}" PATHS "${libdir}" NO_DEFAULT_PATH) + if (NOT _LIB_PATH) + message("Skipping ${target} as ${lib} is missing") + return() + else() + list(APPEND lib_paths "${_LIB_PATH}") + endif() + # Removing _LIB_PATH from cache otherwise it won't be updated + # on the next call to find_library(). + unset(_LIB_PATH CACHE) + endforeach() + + message("Adding ${target} target") + add_library(${target} SHARED IMPORTED) + set_target_properties(${target} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${incdir} + IMPORTED_LOCATION ${lib_paths} + ) +endfunction() + +function(add_torchcodec_target ffmpeg_major_version) + set(target torchcodec::core${ffmpeg_major_version}) + + if (NOT TARGET torchcodec::ffmpeg${ffmpeg_major_version}) + message("Skipping ${target} as torchcodec::ffmpeg${ffmpeg_major_version} is not defined") + return() + endif() + + find_library(_LIB_PATH torchcodec_core${ffmpeg_major_version} + PATHS "${TORCHCODEC_INSTALL_PREFIX}" NO_CACHE NO_DEFAULT_PATH) + if (NOT _LIB_PATH) + message("Skipping ${target} as torchcodec_core${ffmpeg_major_version} is missing") + return() + endif() + + message("Adding ${target} target") + add_library(${target} SHARED IMPORTED) + add_dependencies(${target} torchcodec::ffmpeg${ffmpeg_major_version}) + set_target_properties(${target} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${TORCHCODEC_INCLUDE_DIRS} + IMPORTED_LOCATION ${_LIB_PATH} + ) + # Removing _LIB_PATH from cache otherwise it won't be updated + # on the next call to find_library(). + unset(_LIB_PATH CACHE) + + list(APPEND TORCHCODEC_VARIANTS "${ffmpeg_major_version}") + set(TORCHCODEC_VARIANTS "${TORCHCODEC_VARIANTS}" PARENT_SCOPE) +endfunction() + +if (DEFINED ENV{TORCHCODEC_FFMPEG4_INSTALL_PREFIX} OR + DEFINED ENV{TORCHCODEC_FFMPEG5_INSTALL_PREFIX} OR + DEFINED ENV{TORCHCODEC_FFMPEG6_INSTALL_PREFIX} OR + DEFINED ENV{TORCHCODEC_FFMPEG7_INSTALL_PREFIX}) + if (UNIX AND NOT APPLE) + set(f4_library_file_names + libavutil.so.56 + libavcodec.so.58 + libavformat.so.58 + libavdevice.so.58 + libavfilter.so.7 + libswscale.so.5 + libswresample.so.3 + ) + set(f5_library_file_names + libavutil.so.57 + libavcodec.so.59 + libavformat.so.59 + libavdevice.so.59 + libavfilter.so.8 + libswscale.so.6 + libswresample.so.4 + ) + set(f6_library_file_names + libavutil.so.58 + libavcodec.so.60 + libavformat.so.60 + libavdevice.so.60 + libavfilter.so.9 + libswscale.so.7 + libswresample.so.4 + ) + set(f7_library_file_names + libavutil.so.59 + libavcodec.so.61 + libavformat.so.61 + libavdevice.so.61 + libavfilter.so.10 + libswscale.so.8 + libswresample.so.5 + ) + endif() + + add_ffmpeg_target(4 "${f4_library_file_names}") + add_ffmpeg_target(5 "${f5_library_file_names}") + add_ffmpeg_target(6 "${f6_library_file_names}") + add_ffmpeg_target(7 "${f7_library_file_names}") + + add_torchcodec_target(4) + add_torchcodec_target(5) + add_torchcodec_target(6) + add_torchcodec_target(7) +else() + find_package(PkgConfig REQUIRED) + pkg_check_modules(TORCHCODEC_LIBAV IMPORTED_TARGET + libavdevice + libavfilter + libavformat + libavcodec + libavutil + libswresample + libswscale + ) + + if (TARGET PkgConfig::TORCHCODEC_LIBAV) + # Split libavcodec's version string by '.' and convert it to a list + string(REPLACE "." ";" libavcodec_version_list ${TORCHCODEC_LIBAV_libavcodec_VERSION}) + # Get the first element of the list, which is the major version + list(GET libavcodec_version_list 0 libavcodec_major_version) + + if (${libavcodec_major_version} STREQUAL "58") + set(ffmpeg_major_version "4") + elseif (${libavcodec_major_version} STREQUAL "59") + set(ffmpeg_major_version "5") + elseif (${libavcodec_major_version} STREQUAL "60") + set(ffmpeg_major_version "6") + elseif (${libavcodec_major_version} STREQUAL "61") + set(ffmpeg_major_version "7") + endif() + + if (libavcodec_major_version) + message("Adding torchcodec::ffmpeg${ffmpeg_major_version} target") + add_library(torchcodec::ffmpeg${ffmpeg_major_version} ALIAS PkgConfig::TORCHCODEC_LIBAV) + add_torchcodec_target(${ffmpeg_major_version}) + endif() + endif() +endif() + +find_package_handle_standard_args(TorchCodec DEFAULT_MSG TORCHCODEC_VARIANTS)