[Libav-user] AVFilter with hardware transcoding

Luis Felipe Domínguez Vega ldominguez at boldmss.com
Mon Jan 16 21:32:10 EET 2023


Hi, I trying to apply "yadif_cuda,scale_cuda" filter to a transcoder 
app. The problem is with the Pixel Format.

I'm using 'h264' as decoder and 'h264_nvenc' as encoder, selected CUDA 
device as hardware context and this is working great, the problem is 
when i "insert in the middle" the filter process.

The filter that i trying to use is 
"hwupload_cuda,yadif_cuda,scale_cuda=w=100:h=100" and the code for init 
filters is at the end.

One of the thing that I dont underestand well is that when you init the 
filter (the "in") you must pass the pix_fmt, but the problem is, the 
image is on yuv420p format, but at real the hardware decoding process 
put the decoded frame with cuda format, so, how work with this 2 formats.

static int init_filters(const char *filtersDescr) {

     int ret = 0;

     const AVFilter *bufferSrc  = avfilter_get_by_name("buffer");
     const AVFilter *bufferSink = avfilter_get_by_name("buffersink");
     AVFilterInOut *outputs = avfilter_inout_alloc();
     AVFilterInOut *inputs  = avfilter_inout_alloc();

     AVRational time_base = dFmtCtx->streams[videoStream]->time_base;

     filterGraph = avfilter_graph_alloc();

     if (!outputs || !inputs || !filterGraph) {
         ret = AVERROR(ENOMEM);

         avfilter_inout_free(&inputs);
         avfilter_inout_free(&outputs);

         return ret;
     }

     spdlog::debug("Init filter with input format: {} {}", 
dvCodecCtx->pix_fmt, dvCodecCtx->sw_pix_fmt);

     char args[512];
     snprintf(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
             dvCodecCtx->width, dvCodecCtx->height, AV_PIX_FMT_CUDA,
             time_base.num, time_base.den,
             dvCodecCtx->sample_aspect_ratio.num, 
dvCodecCtx->sample_aspect_ratio.den);


     spdlog::debug("Making 'in' filter");

     ret = avfilter_graph_create_filter(&bufferSrcCtx, bufferSrc, "in",
                                        args, NULL, filterGraph);

     if (ret < 0) {
         av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");

         avfilter_inout_free(&inputs);
         avfilter_inout_free(&outputs);

         return ret;
     }

     spdlog::debug("Making 'out' filter");

      /* buffer video sink: to terminate the filter chain. */
     ret = avfilter_graph_create_filter(&bufferSinkCtx, bufferSink, "out",
                                        NULL, NULL, filterGraph);
     if (ret < 0) {
         av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");

         avfilter_inout_free(&inputs);
         avfilter_inout_free(&outputs);

         return ret;
     }

    /* ret = av_opt_set_int_list(bufferSinkCtx, "pix_fmts", pixFmts,
                               AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
     if (ret < 0) {
         spdlog::error("Cannot set output pixel format");

         avfilter_inout_free(&inputs);
         avfilter_inout_free(&outputs);

         return ret;
     }*/

     outputs->name       = av_strdup("in");
     outputs->filter_ctx = bufferSrcCtx;
     outputs->pad_idx    = 0;
     outputs->next       = NULL;

     inputs->name       = av_strdup("out");
     inputs->filter_ctx = bufferSinkCtx;
     inputs->pad_idx    = 0;
     inputs->next       = NULL;

     spdlog::debug("Parsing custom filter");

     if ((ret = avfilter_graph_parse_ptr(filterGraph, filtersDescr,
                                     &inputs, &outputs, NULL)) < 0){
         avfilter_inout_free(&inputs);
         avfilter_inout_free(&outputs);

         return ret;
     }

     spdlog::debug("Configuring filter graph");

     if ((ret = avfilter_graph_config(filterGraph, NULL)) < 0) {

         avfilter_inout_free(&inputs);
         avfilter_inout_free(&outputs);

         return ret;
     }

     avfilter_inout_free(&inputs);
     avfilter_inout_free(&outputs);

     return ret;
}



More information about the Libav-user mailing list