Skip to content

Commit c3b71e4

Browse files
Dan-FloresDaniel Flores
andauthored
Enable local builds with FFmpeg8 (#935)
Co-authored-by: Daniel Flores <[email protected]>
1 parent 986f10c commit c3b71e4

File tree

5 files changed

+80
-21
lines changed

5 files changed

+80
-21
lines changed

src/torchcodec/_core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ else()
304304
set(ffmpeg_major_version "6")
305305
elseif (${libavcodec_major_version} STREQUAL "61")
306306
set(ffmpeg_major_version "7")
307+
elseif (${libavcodec_major_version} STREQUAL "62")
308+
set(ffmpeg_major_version "8")
307309
else()
308310
message(
309311
FATAL_ERROR

src/torchcodec/_core/FFMPEGCommon.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
#include <c10/util/Exception.h>
1010

11+
extern "C" {
12+
#include <libavfilter/avfilter.h>
13+
#include <libavfilter/buffersink.h>
14+
}
15+
1116
namespace facebook::torchcodec {
1217

1318
AutoAVPacket::AutoAVPacket() : avPacket_(av_packet_alloc()) {
@@ -374,6 +379,70 @@ SwrContext* createSwrContext(
374379
return swrContext;
375380
}
376381

382+
AVFilterContext* createBuffersinkFilter(
383+
AVFilterGraph* filterGraph,
384+
enum AVPixelFormat outputFormat) {
385+
const AVFilter* buffersink = avfilter_get_by_name("buffersink");
386+
TORCH_CHECK(buffersink != nullptr, "Failed to get buffersink filter.");
387+
388+
AVFilterContext* sinkContext = nullptr;
389+
int status;
390+
const char* filterName = "out";
391+
392+
enum AVPixelFormat pix_fmts[] = {outputFormat, AV_PIX_FMT_NONE};
393+
394+
// av_opt_set_int_list was replaced by av_opt_set_array() in FFmpeg 8.
395+
#if LIBAVUTIL_VERSION_MAJOR >= 60 // FFmpeg >= 8
396+
// Output options like pixel_formats must be set before filter init
397+
sinkContext =
398+
avfilter_graph_alloc_filter(filterGraph, buffersink, filterName);
399+
TORCH_CHECK(
400+
sinkContext != nullptr, "Failed to allocate buffersink filter context.");
401+
402+
// When setting pix_fmts, only the first element is used, so nb_elems = 1
403+
// AV_PIX_FMT_NONE acts as a terminator for the array in av_opt_set_int_list
404+
status = av_opt_set_array(
405+
sinkContext,
406+
"pixel_formats",
407+
AV_OPT_SEARCH_CHILDREN,
408+
0, // start_elem
409+
1, // nb_elems
410+
AV_OPT_TYPE_PIXEL_FMT,
411+
pix_fmts);
412+
TORCH_CHECK(
413+
status >= 0,
414+
"Failed to set pixel format for buffersink filter: ",
415+
getFFMPEGErrorStringFromErrorCode(status));
416+
417+
status = avfilter_init_str(sinkContext, nullptr);
418+
TORCH_CHECK(
419+
status >= 0,
420+
"Failed to initialize buffersink filter: ",
421+
getFFMPEGErrorStringFromErrorCode(status));
422+
#else // FFmpeg <= 7
423+
// For older FFmpeg versions, create filter and then set options
424+
status = avfilter_graph_create_filter(
425+
&sinkContext, buffersink, filterName, nullptr, nullptr, filterGraph);
426+
TORCH_CHECK(
427+
status >= 0,
428+
"Failed to create buffersink filter: ",
429+
getFFMPEGErrorStringFromErrorCode(status));
430+
431+
status = av_opt_set_int_list(
432+
sinkContext,
433+
"pix_fmts",
434+
pix_fmts,
435+
AV_PIX_FMT_NONE,
436+
AV_OPT_SEARCH_CHILDREN);
437+
TORCH_CHECK(
438+
status >= 0,
439+
"Failed to set pixel formats for buffersink filter: ",
440+
getFFMPEGErrorStringFromErrorCode(status));
441+
#endif
442+
443+
return sinkContext;
444+
}
445+
377446
UniqueAVFrame convertAudioAVFrameSamples(
378447
const UniqueSwrContext& swrContext,
379448
const UniqueAVFrame& srcAVFrame,

src/torchcodec/_core/FFMPEGCommon.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,8 @@ int64_t computeSafeDuration(
237237
const AVRational& frameRate,
238238
const AVRational& timeBase);
239239

240+
AVFilterContext* createBuffersinkFilter(
241+
AVFilterGraph* filterGraph,
242+
enum AVPixelFormat outputFormat);
243+
240244
} // namespace facebook::torchcodec

src/torchcodec/_core/FilterGraph.cpp

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// LICENSE file in the root directory of this source tree.
66

77
#include "src/torchcodec/_core/FilterGraph.h"
8+
#include "src/torchcodec/_core/FFMPEGCommon.h"
89

910
extern "C" {
1011
#include <libavfilter/buffersink.h>
@@ -63,7 +64,6 @@ FilterGraph::FilterGraph(
6364
}
6465

6566
const AVFilter* buffersrc = avfilter_get_by_name("buffer");
66-
const AVFilter* buffersink = avfilter_get_by_name("buffersink");
6767

6868
UniqueAVBufferSrcParameters srcParams(av_buffersrc_parameters_alloc());
6969
TORCH_CHECK(srcParams, "Failed to allocate buffersrc params");
@@ -93,26 +93,10 @@ FilterGraph::FilterGraph(
9393
"Failed to create filter graph : ",
9494
getFFMPEGErrorStringFromErrorCode(status));
9595

96-
status = avfilter_graph_create_filter(
97-
&sinkContext_, buffersink, "out", nullptr, nullptr, filterGraph_.get());
96+
sinkContext_ =
97+
createBuffersinkFilter(filterGraph_.get(), filtersContext.outputFormat);
9898
TORCH_CHECK(
99-
status >= 0,
100-
"Failed to create filter graph: ",
101-
getFFMPEGErrorStringFromErrorCode(status));
102-
103-
enum AVPixelFormat pix_fmts[] = {
104-
filtersContext.outputFormat, AV_PIX_FMT_NONE};
105-
106-
status = av_opt_set_int_list(
107-
sinkContext_,
108-
"pix_fmts",
109-
pix_fmts,
110-
AV_PIX_FMT_NONE,
111-
AV_OPT_SEARCH_CHILDREN);
112-
TORCH_CHECK(
113-
status >= 0,
114-
"Failed to set output pixel formats: ",
115-
getFFMPEGErrorStringFromErrorCode(status));
99+
sinkContext_ != nullptr, "Failed to create and configure buffersink");
116100

117101
UniqueAVFilterInOut outputs(avfilter_inout_alloc());
118102
UniqueAVFilterInOut inputs(avfilter_inout_alloc());

src/torchcodec/_core/ops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def load_torchcodec_shared_libraries():
4141
# libraries do not meet those conditions.
4242

4343
exceptions = []
44-
for ffmpeg_major_version in (7, 6, 5, 4):
44+
for ffmpeg_major_version in (8, 7, 6, 5, 4):
4545
pybind_ops_module_name = _get_pybind_ops_module_name(ffmpeg_major_version)
4646
decoder_library_name = f"libtorchcodec_core{ffmpeg_major_version}"
4747
custom_ops_library_name = f"libtorchcodec_custom_ops{ffmpeg_major_version}"

0 commit comments

Comments
 (0)