Skip to content

Commit 0c50c0c

Browse files
committed
Split initialize_video into initialize_video_decoding and initialize_color_conversion
1 parent d115fcc commit 0c50c0c

9 files changed

Lines changed: 76 additions & 64 deletions

src/torchcodec/_core/BetaCudaDeviceInterface.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -324,16 +324,21 @@ BetaCudaDeviceInterface::BetaCudaDeviceInterface(const StableDevice& device)
324324
nvcuvid_available_ = load_nvcuvid_library();
325325
}
326326

327-
void BetaCudaDeviceInterface::initialize_video(
328-
const AVStream* av_stream,
329-
const UniqueDecodingAVFormatContext& av_format_ctx,
327+
void BetaCudaDeviceInterface::initialize_color_conversion(
330328
const VideoStreamOptions& video_stream_options,
331329
const std::vector<std::unique_ptr<Transform>>& transforms,
332330
const std::optional<FrameDims>& resized_output_dims) {
333-
// TODO_API_BREAKDOWN P0
334-
if (!av_stream) {
335-
return;
331+
output_dtype_ = video_stream_options.output_dtype;
332+
if (cpu_fallback_) {
333+
cpu_fallback_->initialize_color_conversion(
334+
video_stream_options, transforms, resized_output_dims);
336335
}
336+
}
337+
338+
void BetaCudaDeviceInterface::initialize_video_decoding(
339+
const AVStream* av_stream,
340+
const UniqueDecodingAVFormatContext& av_format_ctx,
341+
const VideoStreamOptions& video_stream_options) {
337342
STD_TORCH_CHECK(av_stream != nullptr, "AVStream cannot be null");
338343
CudaContextGuard context_guard(device_.index());
339344
rotation_ = rotation_from_degrees(get_rotation_from_stream(av_stream));
@@ -354,12 +359,8 @@ void BetaCudaDeviceInterface::initialize_video(
354359
STD_TORCH_CHECK(
355360
cpu_fallback_ != nullptr, "Failed to create CPU device interface");
356361
cpu_fallback_->initialize(codec_context_);
357-
cpu_fallback_->initialize_video(
358-
av_stream,
359-
av_format_ctx,
360-
video_stream_options,
361-
transforms,
362-
resized_output_dims);
362+
cpu_fallback_->initialize_video_decoding(
363+
av_stream, av_format_ctx, video_stream_options);
363364
return;
364365
}
365366

src/torchcodec/_core/BetaCudaDeviceInterface.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,12 @@ class BetaCudaDeviceInterface : public DeviceInterface {
4545

4646
void initialize(const SharedAVCodecContext& codec_context) override;
4747

48-
void initialize_video(
48+
void initialize_video_decoding(
4949
const AVStream* av_stream,
5050
const UniqueDecodingAVFormatContext& av_format_ctx,
51+
const VideoStreamOptions& video_stream_options) override;
52+
53+
void initialize_color_conversion(
5154
const VideoStreamOptions& video_stream_options,
5255
const std::vector<std::unique_ptr<Transform>>& transforms,
5356
const std::optional<FrameDims>& resized_output_dims) override;

src/torchcodec/_core/ColorConverter.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,10 @@ ColorConverter::ColorConverter(const StableDevice& device) {
2828
// TODO_API_BREAKDOWN P1 It seems unnatural that the color-converter needs its
2929
// own device_interface_, but at the same time the color-conversion *must* be
3030
// third-party aware, and the only way to achieve that for now is via the
31-
// interface. Should at the very least write a note about this design that now
32-
// the DeviceInterface has different modes: decode only, color-convert only,
33-
// and decode+color-convert (which used to be the only mode).
34-
35-
// TODO_API_BREAKDOWN P0: we shouldn't call initialize_video here, this is for
36-
// the decoding+color-convert mode. We should do something cleaner e.g.
37-
// initialize_color_convertion_only()
31+
// interface.
3832
std::vector<std::unique_ptr<Transform>> no_transforms;
39-
device_interface_->initialize_video(
40-
/*av_stream=*/nullptr,
41-
UniqueDecodingAVFormatContext{},
42-
options,
43-
no_transforms,
44-
/*resized_output_dims=*/std::nullopt);
33+
device_interface_->initialize_color_conversion(
34+
options, no_transforms, /*resized_output_dims=*/std::nullopt);
4535
}
4636

4737
torch::stable::Tensor ColorConverter::convert(const AVFrame& av_frame) {

src/torchcodec/_core/CpuDeviceInterface.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,18 @@ void CpuDeviceInterface::initialize(const SharedAVCodecContext& codec_context) {
8080
codec_context_ = codec_context;
8181
}
8282

83-
void CpuDeviceInterface::initialize_video(
83+
void CpuDeviceInterface::initialize_video_decoding(
8484
const AVStream* av_stream,
8585
[[maybe_unused]] const UniqueDecodingAVFormatContext& av_format_ctx,
86+
[[maybe_unused]] const VideoStreamOptions& video_stream_options) {
87+
STD_TORCH_CHECK(av_stream != nullptr, "avStream is null");
88+
time_base_ = av_stream->time_base;
89+
}
90+
91+
void CpuDeviceInterface::initialize_color_conversion(
8692
const VideoStreamOptions& video_stream_options,
8793
const std::vector<std::unique_ptr<Transform>>& transforms,
8894
const std::optional<FrameDims>& resized_output_dims) {
89-
// TODO_API_BREAKDOWN P0 this used to be:
90-
// STD_TORCH_CHECK(av_stream != nullptr, "avStream is null");
91-
// time_base_ = av_stream->time_base;
92-
// but now that avStrean can be null (to create a standalone color converter)
93-
// we need this workaround. This is bad, we need to preserve the previous
94-
// check somehow. See corresponding TODO in color-converter and packet decoder
95-
// code.
96-
time_base_ = (av_stream != nullptr) ? av_stream->time_base
97-
: AVRational{1, AV_TIME_BASE};
9895
av_media_type_ = AVMEDIA_TYPE_VIDEO;
9996
video_stream_options_ = video_stream_options;
10097
resized_output_dims_ = resized_output_dims;

src/torchcodec/_core/CpuDeviceInterface.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@ class CpuDeviceInterface : public DeviceInterface {
2727

2828
virtual void initialize(const SharedAVCodecContext& codec_context) override;
2929

30-
virtual void initialize_video(
30+
virtual void initialize_video_decoding(
3131
const AVStream* av_stream,
3232
const UniqueDecodingAVFormatContext& av_format_ctx,
33+
const VideoStreamOptions& video_stream_options) override;
34+
35+
virtual void initialize_color_conversion(
3336
const VideoStreamOptions& video_stream_options,
3437
const std::vector<std::unique_ptr<Transform>>& transforms,
3538
const std::optional<FrameDims>& resized_output_dims) override;
@@ -76,7 +79,11 @@ class CpuDeviceInterface : public DeviceInterface {
7679
const FrameDims& output_dims) const;
7780

7881
VideoStreamOptions video_stream_options_;
79-
AVRational time_base_;
82+
// Default used when color conversion runs standalone (no stream to derive it
83+
// from, e.g. the ColorConverter block API). initialize_video_decoding()
84+
// overrides it from the stream when there is one. Its value doesn't matter on
85+
// color-conversion-only mode, but filtergraph still expects it.
86+
AVRational time_base_ = {1, AV_TIME_BASE};
8087
AVPixelFormat output_pixel_format_;
8188

8289
// If the resized output dimensions are present, then we always use those as

src/torchcodec/_core/CudaDeviceInterface.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,13 @@ void CudaDeviceInterface::initialize(
114114
codec_context_ = codec_context;
115115
}
116116

117-
void CudaDeviceInterface::initialize_video(
117+
void CudaDeviceInterface::initialize_video_decoding(
118118
const AVStream* av_stream,
119119
const UniqueDecodingAVFormatContext& av_format_ctx,
120-
const VideoStreamOptions& video_stream_options,
121-
[[maybe_unused]] const std::vector<std::unique_ptr<Transform>>& transforms,
122-
[[maybe_unused]] const std::optional<FrameDims>& resized_output_dims) {
120+
[[maybe_unused]] const VideoStreamOptions& video_stream_options) {
123121
STD_TORCH_CHECK(av_stream != nullptr, "avStream is null");
124122
time_base_ = av_stream->time_base;
125-
video_stream_options_ = video_stream_options;
126123

127-
// TODO: Ideally, we should keep all interface implementations independent.
128124
cpu_interface_ = create_device_interface(kStableCPU);
129125
STD_TORCH_CHECK(
130126
cpu_interface_ != nullptr, "Failed to create CPU device interface");
@@ -137,6 +133,13 @@ void CudaDeviceInterface::initialize_video(
137133
/*resizedOutputDims=*/std::nullopt);
138134
}
139135

136+
void CudaDeviceInterface::initialize_color_conversion(
137+
const VideoStreamOptions& video_stream_options,
138+
[[maybe_unused]] const std::vector<std::unique_ptr<Transform>>& transforms,
139+
[[maybe_unused]] const std::optional<FrameDims>& resized_output_dims) {
140+
video_stream_options_ = video_stream_options;
141+
}
142+
140143
void CudaDeviceInterface::register_hardware_device_with_codec(
141144
AVCodecContext* codec_context) {
142145
STD_TORCH_CHECK(

src/torchcodec/_core/CudaDeviceInterface.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ class CudaDeviceInterface : public DeviceInterface {
2828

2929
void initialize(const SharedAVCodecContext& codec_context) override;
3030

31-
void initialize_video(
31+
void initialize_video_decoding(
3232
const AVStream* av_stream,
3333
const UniqueDecodingAVFormatContext& av_format_ctx,
34+
const VideoStreamOptions& video_stream_options) override;
35+
36+
void initialize_color_conversion(
3437
const VideoStreamOptions& video_stream_options,
35-
[[maybe_unused]] const std::vector<std::unique_ptr<Transform>>&
36-
transforms,
37-
[[maybe_unused]] const std::optional<FrameDims>& resized_output_dims)
38-
override;
38+
const std::vector<std::unique_ptr<Transform>>& transforms,
39+
const std::optional<FrameDims>& resized_output_dims) override;
3940

4041
void register_hardware_device_with_codec(
4142
AVCodecContext* codec_context) override;

src/torchcodec/_core/DeviceInterface.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,33 @@ class DeviceInterface {
5656
// default sendPacket/receiveFrame/flush implementations.
5757
virtual void initialize(const SharedAVCodecContext& codec_context) = 0;
5858

59-
// Initialize the device with parameters specific to video decoding. There is
60-
// a default empty implementation.
61-
virtual void initialize_video(
59+
// Initialize state needed to decode packets into raw AVFrames.
60+
virtual void initialize_video_decoding(
6261
[[maybe_unused]] const AVStream* av_stream,
6362
[[maybe_unused]] const UniqueDecodingAVFormatContext& av_format_ctx,
63+
[[maybe_unused]] const VideoStreamOptions& video_stream_options) {}
64+
65+
// Initialize state needed to color-convert decoded AVFrames into output
66+
// tensors.
67+
virtual void initialize_color_conversion(
6468
[[maybe_unused]] const VideoStreamOptions& video_stream_options,
6569
[[maybe_unused]] const std::vector<std::unique_ptr<Transform>>&
66-
transforms,
67-
[[maybe_unused]] const std::optional<FrameDims>& resized_output_dims) {}
70+
transforms = {},
71+
[[maybe_unused]] const std::optional<FrameDims>& resized_output_dims =
72+
std::nullopt) {}
73+
74+
// Convenience for the combined decode + color-convert path, kept for BC as
75+
// it's used by SingleStreamDecoder and out-of-tree interfaces rely on it.
76+
void initialize_video(
77+
const AVStream* av_stream,
78+
const UniqueDecodingAVFormatContext& av_format_ctx,
79+
const VideoStreamOptions& video_stream_options,
80+
const std::vector<std::unique_ptr<Transform>>& transforms,
81+
const std::optional<FrameDims>& resized_output_dims) {
82+
initialize_video_decoding(av_stream, av_format_ctx, video_stream_options);
83+
initialize_color_conversion(
84+
video_stream_options, transforms, resized_output_dims);
85+
}
6886

6987
// Initialize the device with parameters specific to audio decoding. There is
7088
// a default empty implementation.

src/torchcodec/_core/PacketDecoder.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,8 @@ PacketDecoder::PacketDecoder(
7575
options.output_dtype = OutputDtype::UINT8; // dtype not exposed yet
7676
options.device = device;
7777

78-
// TODO_API_BREAKDOWN P0: This isn't right, it's needed only for the NVDEC
79-
// interface. This should probably be initialize_video_only - there's a
80-
// sibling TODO in the ColorConverter code (about color-conversion only.)
81-
std::vector<std::unique_ptr<Transform>> no_transforms;
82-
device_interface_->initialize_video(
83-
stream,
84-
demuxer.format_context(),
85-
options,
86-
no_transforms,
87-
/*resized_output_dims=*/std::nullopt);
78+
device_interface_->initialize_video_decoding(
79+
stream, demuxer.format_context(), options);
8880
}
8981

9082
int PacketDecoder::send_packet(AVPacket* packet) {

0 commit comments

Comments
 (0)