Skip to content

Commit fca8b83

Browse files
committed
Merge branch 'main' of github.com:pytorch/torchcodec into crop_transform
2 parents 8f4507b + 3827dfe commit fca8b83

19 files changed

+193
-148
lines changed

.github/workflows/linux_wheel.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,14 @@ jobs:
7171
name: meta-pytorch_torchcodec__${{ matrix.python-version }}_cpu_x86_64
7272
path: pytorch/torchcodec/dist/
7373
- name: Setup conda env
74-
uses: conda-incubator/setup-miniconda@v2
74+
uses: conda-incubator/setup-miniconda@v3
7575
with:
7676
auto-update-conda: true
77-
miniconda-version: "latest"
77+
# Using miniforge instead of miniconda ensures that the default
78+
# conda channel is conda-forge instead of main/default. This ensures
79+
# ABI consistency between dependencies:
80+
# https://conda-forge.org/docs/user/transitioning_from_defaults/
81+
miniforge-version: latest
7882
activate-environment: test
7983
python-version: ${{ matrix.python-version }}
8084
- 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`:

src/torchcodec/_core/BetaCudaDeviceInterface.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ BetaCudaDeviceInterface::~BetaCudaDeviceInterface() {
230230

231231
void BetaCudaDeviceInterface::initialize(
232232
const AVStream* avStream,
233-
const UniqueDecodingAVFormatContext& avFormatCtx) {
233+
const UniqueDecodingAVFormatContext& avFormatCtx,
234+
[[maybe_unused]] const SharedAVCodecContext& codecContext) {
234235
TORCH_CHECK(avStream != nullptr, "AVStream cannot be null");
235236
timeBase_ = avStream->time_base;
236237
frameRateAvgFromFFmpeg_ = avStream->r_frame_rate;

src/torchcodec/_core/BetaCudaDeviceInterface.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,15 @@ class BetaCudaDeviceInterface : public DeviceInterface {
4040

4141
void initialize(
4242
const AVStream* avStream,
43-
const UniqueDecodingAVFormatContext& avFormatCtx) override;
43+
const UniqueDecodingAVFormatContext& avFormatCtx,
44+
const SharedAVCodecContext& codecContext) override;
4445

4546
void convertAVFrameToFrameOutput(
4647
UniqueAVFrame& avFrame,
4748
FrameOutput& frameOutput,
4849
std::optional<torch::Tensor> preAllocatedOutputTensor =
4950
std::nullopt) override;
5051

51-
bool canDecodePacketDirectly() const override {
52-
return true;
53-
}
54-
5552
int sendPacket(ReferenceAVPacket& packet) override;
5653
int sendEOFPacket() override;
5754
int receiveFrame(UniqueAVFrame& avFrame) override;

src/torchcodec/_core/CpuDeviceInterface.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ CpuDeviceInterface::CpuDeviceInterface(const torch::Device& device)
4848

4949
void CpuDeviceInterface::initialize(
5050
const AVStream* avStream,
51-
[[maybe_unused]] const UniqueDecodingAVFormatContext& avFormatCtx) {
51+
[[maybe_unused]] const UniqueDecodingAVFormatContext& avFormatCtx,
52+
const SharedAVCodecContext& codecContext) {
5253
TORCH_CHECK(avStream != nullptr, "avStream is null");
54+
codecContext_ = codecContext;
5355
timeBase_ = avStream->time_base;
5456
}
5557

src/torchcodec/_core/CpuDeviceInterface.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ class CpuDeviceInterface : public DeviceInterface {
2525

2626
virtual void initialize(
2727
const AVStream* avStream,
28-
const UniqueDecodingAVFormatContext& avFormatCtx) override;
28+
const UniqueDecodingAVFormatContext& avFormatCtx,
29+
const SharedAVCodecContext& codecContext) override;
2930

3031
virtual void initializeVideo(
3132
const VideoStreamOptions& videoStreamOptions,

src/torchcodec/_core/CudaDeviceInterface.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,17 @@ CudaDeviceInterface::~CudaDeviceInterface() {
114114

115115
void CudaDeviceInterface::initialize(
116116
const AVStream* avStream,
117-
const UniqueDecodingAVFormatContext& avFormatCtx) {
117+
const UniqueDecodingAVFormatContext& avFormatCtx,
118+
const SharedAVCodecContext& codecContext) {
118119
TORCH_CHECK(avStream != nullptr, "avStream is null");
120+
codecContext_ = codecContext;
119121
timeBase_ = avStream->time_base;
120122

121123
// TODO: Ideally, we should keep all interface implementations independent.
122124
cpuInterface_ = createDeviceInterface(torch::kCPU);
123125
TORCH_CHECK(
124126
cpuInterface_ != nullptr, "Failed to create CPU device interface");
125-
cpuInterface_->initialize(avStream, avFormatCtx);
127+
cpuInterface_->initialize(avStream, avFormatCtx, codecContext);
126128
cpuInterface_->initializeVideo(
127129
VideoStreamOptions(),
128130
{},

src/torchcodec/_core/CudaDeviceInterface.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ class CudaDeviceInterface : public DeviceInterface {
2222

2323
void initialize(
2424
const AVStream* avStream,
25-
const UniqueDecodingAVFormatContext& avFormatCtx) override;
25+
const UniqueDecodingAVFormatContext& avFormatCtx,
26+
const SharedAVCodecContext& codecContext) override;
2627

2728
void initializeVideo(
2829
const VideoStreamOptions& videoStreamOptions,

src/torchcodec/_core/DeviceInterface.h

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ class DeviceInterface {
5454
// Initialize the device with parameters generic to all kinds of decoding.
5555
virtual void initialize(
5656
const AVStream* avStream,
57-
const UniqueDecodingAVFormatContext& avFormatCtx) = 0;
57+
const UniqueDecodingAVFormatContext& avFormatCtx,
58+
const SharedAVCodecContext& codecContext) = 0;
5859

5960
// Initialize the device with parameters specific to video decoding. There is
6061
// a default empty implementation.
@@ -80,52 +81,47 @@ class DeviceInterface {
8081
// Extension points for custom decoding paths
8182
// ------------------------------------------
8283

83-
// Override to return true if this device interface can decode packets
84-
// directly. This means that the following two member functions can both
85-
// be called:
86-
//
87-
// 1. sendPacket()
88-
// 2. receiveFrame()
89-
virtual bool canDecodePacketDirectly() const {
90-
return false;
91-
}
92-
93-
// Moral equivalent of avcodec_send_packet()
9484
// Returns AVSUCCESS on success, AVERROR(EAGAIN) if decoder queue full, or
9585
// other AVERROR on failure
96-
virtual int sendPacket([[maybe_unused]] ReferenceAVPacket& avPacket) {
86+
// Default implementation uses FFmpeg directly
87+
virtual int sendPacket(ReferenceAVPacket& avPacket) {
9788
TORCH_CHECK(
98-
false,
99-
"Send/receive packet decoding not implemented for this device interface");
100-
return AVERROR(ENOSYS);
89+
codecContext_ != nullptr,
90+
"Codec context not available for default packet sending");
91+
return avcodec_send_packet(codecContext_.get(), avPacket.get());
10192
}
10293

10394
// Send an EOF packet to flush the decoder
10495
// Returns AVSUCCESS on success, or other AVERROR on failure
96+
// Default implementation uses FFmpeg directly
10597
virtual int sendEOFPacket() {
10698
TORCH_CHECK(
107-
false, "Send EOF packet not implemented for this device interface");
108-
return AVERROR(ENOSYS);
99+
codecContext_ != nullptr,
100+
"Codec context not available for default EOF packet sending");
101+
return avcodec_send_packet(codecContext_.get(), nullptr);
109102
}
110103

111-
// Moral equivalent of avcodec_receive_frame()
112104
// Returns AVSUCCESS on success, AVERROR(EAGAIN) if no frame ready,
113105
// AVERROR_EOF if end of stream, or other AVERROR on failure
114-
virtual int receiveFrame([[maybe_unused]] UniqueAVFrame& avFrame) {
106+
// Default implementation uses FFmpeg directly
107+
virtual int receiveFrame(UniqueAVFrame& avFrame) {
115108
TORCH_CHECK(
116-
false,
117-
"Send/receive packet decoding not implemented for this device interface");
118-
return AVERROR(ENOSYS);
109+
codecContext_ != nullptr,
110+
"Codec context not available for default frame receiving");
111+
return avcodec_receive_frame(codecContext_.get(), avFrame.get());
119112
}
120113

121114
// Flush remaining frames from decoder
122115
virtual void flush() {
123-
// Default implementation is no-op for standard decoders
124-
// Custom decoders can override this method
116+
TORCH_CHECK(
117+
codecContext_ != nullptr,
118+
"Codec context not available for default flushing");
119+
avcodec_flush_buffers(codecContext_.get());
125120
}
126121

127122
protected:
128123
torch::Device device_;
124+
SharedAVCodecContext codecContext_;
129125
};
130126

131127
using CreateDeviceInterfaceFn =

src/torchcodec/_core/FFMPEGCommon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ int getNumChannels(const UniqueAVFrame& avFrame) {
149149
#endif
150150
}
151151

152-
int getNumChannels(const UniqueAVCodecContext& avCodecContext) {
152+
int getNumChannels(const SharedAVCodecContext& avCodecContext) {
153153
#if LIBAVFILTER_VERSION_MAJOR > 8 || \
154154
(LIBAVFILTER_VERSION_MAJOR == 8 && LIBAVFILTER_VERSION_MINOR >= 44)
155155
return avCodecContext->ch_layout.nb_channels;

0 commit comments

Comments
 (0)