|
8 | 8 |
|
9 | 9 | #include <c10/util/Exception.h>
|
10 | 10 |
|
| 11 | +extern "C" { |
| 12 | +#include <libavfilter/avfilter.h> |
| 13 | +#include <libavfilter/buffersink.h> |
| 14 | +} |
| 15 | + |
11 | 16 | namespace facebook::torchcodec {
|
12 | 17 |
|
13 | 18 | AutoAVPacket::AutoAVPacket() : avPacket_(av_packet_alloc()) {
|
@@ -374,6 +379,70 @@ SwrContext* createSwrContext(
|
374 | 379 | return swrContext;
|
375 | 380 | }
|
376 | 381 |
|
| 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 | + |
377 | 446 | UniqueAVFrame convertAudioAVFrameSamples(
|
378 | 447 | const UniqueSwrContext& swrContext,
|
379 | 448 | const UniqueAVFrame& srcAVFrame,
|
|
0 commit comments