scale_rga report "No hw context provided on input" #137

Closed
opened 2025-12-23 10:34:01 +01:00 by backuprepo · 8 comments
Owner

Originally created by @cnjswwxbtcc on GitHub (Dec 28, 2024).

I want to use the 'scale_rga' filter in my cpp code, which is used to convert the image size; However, the following error message is output.

[scale_rkrga @ 0x7f90005c00] No hw context provided on input
[scale_rkrga @ 0x7f90005c00] Failed to configure output pad on scale_rkrga

I tryed ffmpeg -hwaccel rkmpp -hwaccel_output_format drm_prime -i input.mp4 -an -sn -vf scale_rkrga=w=720:h=480:format=yuv420p,hwdownload,format=yuv420p -f rawvideo - > /dev/null, and it works well;
error message is caused by, sorry, i have no idea about this hw_frames_ctx, and how it should be initialized:
libavfilter/vf_vpp_rkrga.c

    if (!inlink->hw_frames_ctx) {
        av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n");
        return AVERROR(EINVAL);
    }

The final part is my code flow:

    const AVFilter *buffersrc = avfilter_get_by_name("buffer");
    snprintf(args, sizeof(args),
             "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
             videoCtx->inWidth, videoCtx->inHeight, AV_PIX_FMT_DRM_PRIME,
             videoCtx->codecCtx->pkt_timebase.num, videoCtx->codecCtx->pkt_timebase.den,
             videoCtx->codecCtx->sample_aspect_ratio.num, videoCtx->codecCtx->sample_aspect_ratio.den);

    // 创建 buffer 源滤镜(输入滤镜)
    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, nullptr, filter_graph);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Cannot create buffer source\n");
        return false;
    }

    // 创建 scale_rkrga 滤镜
    const AVFilter *scale_rkrga_filter = avfilter_get_by_name("scale_rkrga");
    if (!scale_rkrga_filter) {
        av_log(nullptr, AV_LOG_ERROR, "scale_rkrga filter not found\n");
        return false;
    }
    snprintf(scale_args, sizeof(scale_args), "w=%d:h=%d:format=rgba", videoCtx->outHeight, videoCtx->outHeight);
    ret = avfilter_graph_create_filter(&scale_rkrga_ctx, scale_rkrga_filter, "scale_rkrga", scale_args, nullptr, filter_graph);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Cannot create scale_rkrga filter\n");
        return false;
    }

    //创建 hwdownload 滤镜
    const AVFilter *hwdownload_filter = avfilter_get_by_name("hwdownload");
    ret = avfilter_graph_create_filter(&hwdownload_ctx, hwdownload_filter, "hwdownload",
                                    NULL, NULL, filter_graph);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Cannot create hwdownload filter\n");
        return false;
    }

    //创建 format 滤镜
    const AVFilter *format_filter = avfilter_get_by_name("format");
    const char *format_args = "yuv420p";
    ret = avfilter_graph_create_filter(&format_ctx, format_filter, "format",
                                    format_args, NULL, filter_graph);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Cannot create format filter\n");
        return false;
    }


    // 创建 buffer sink 滤镜(输出滤镜)
    const AVFilter *buffersink = avfilter_get_by_name("buffersink");
    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", nullptr, nullptr, filter_graph);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Cannot create buffer sink\n");
        return false;
    }

    // 链接滤镜:输入 -> scale_rkrga -> 输出
    ret = avfilter_link(buffersrc_ctx, 0, scale_rkrga_ctx, 0);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Error linking filters src--scale\n");
        return false;
    }
    ret = avfilter_link(scale_rkrga_ctx, 0, hwdownload_ctx, 0);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Error linking filters scale--hwdownload\n");
        return false;
    }
    ret = avfilter_link(hwdownload_ctx, 0, buffersink_ctx, 0);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Error linking filters hwload--sink\n");
        return false;
    }

    ret = avfilter_graph_config(filter_graph, nullptr);
    if (ret < 0) {
        av_log(nullptr, AV_LOG_ERROR, "Error configuring the filter graph\n");
        return false;
    }
Originally created by @cnjswwxbtcc on GitHub (Dec 28, 2024). I want to use the 'scale_rga' filter in my cpp code, which is used to convert the image size; However, the following error message is output. ```bash [scale_rkrga @ 0x7f90005c00] No hw context provided on input [scale_rkrga @ 0x7f90005c00] Failed to configure output pad on scale_rkrga ``` I tryed `ffmpeg -hwaccel rkmpp -hwaccel_output_format drm_prime -i input.mp4 -an -sn -vf scale_rkrga=w=720:h=480:format=yuv420p,hwdownload,format=yuv420p -f rawvideo - > /dev/null`, and it works well; error message is caused by, sorry, i have no idea about this `hw_frames_ctx`, and how it should be initialized: libavfilter/vf_vpp_rkrga.c ```c if (!inlink->hw_frames_ctx) { av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); return AVERROR(EINVAL); } ``` The final part is my code flow: ```cpp const AVFilter *buffersrc = avfilter_get_by_name("buffer"); snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d", videoCtx->inWidth, videoCtx->inHeight, AV_PIX_FMT_DRM_PRIME, videoCtx->codecCtx->pkt_timebase.num, videoCtx->codecCtx->pkt_timebase.den, videoCtx->codecCtx->sample_aspect_ratio.num, videoCtx->codecCtx->sample_aspect_ratio.den); // 创建 buffer 源滤镜(输入滤镜) ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, nullptr, filter_graph); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Cannot create buffer source\n"); return false; } // 创建 scale_rkrga 滤镜 const AVFilter *scale_rkrga_filter = avfilter_get_by_name("scale_rkrga"); if (!scale_rkrga_filter) { av_log(nullptr, AV_LOG_ERROR, "scale_rkrga filter not found\n"); return false; } snprintf(scale_args, sizeof(scale_args), "w=%d:h=%d:format=rgba", videoCtx->outHeight, videoCtx->outHeight); ret = avfilter_graph_create_filter(&scale_rkrga_ctx, scale_rkrga_filter, "scale_rkrga", scale_args, nullptr, filter_graph); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Cannot create scale_rkrga filter\n"); return false; } //创建 hwdownload 滤镜 const AVFilter *hwdownload_filter = avfilter_get_by_name("hwdownload"); ret = avfilter_graph_create_filter(&hwdownload_ctx, hwdownload_filter, "hwdownload", NULL, NULL, filter_graph); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Cannot create hwdownload filter\n"); return false; } //创建 format 滤镜 const AVFilter *format_filter = avfilter_get_by_name("format"); const char *format_args = "yuv420p"; ret = avfilter_graph_create_filter(&format_ctx, format_filter, "format", format_args, NULL, filter_graph); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Cannot create format filter\n"); return false; } // 创建 buffer sink 滤镜(输出滤镜) const AVFilter *buffersink = avfilter_get_by_name("buffersink"); ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out", nullptr, nullptr, filter_graph); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Cannot create buffer sink\n"); return false; } // 链接滤镜:输入 -> scale_rkrga -> 输出 ret = avfilter_link(buffersrc_ctx, 0, scale_rkrga_ctx, 0); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Error linking filters src--scale\n"); return false; } ret = avfilter_link(scale_rkrga_ctx, 0, hwdownload_ctx, 0); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Error linking filters scale--hwdownload\n"); return false; } ret = avfilter_link(hwdownload_ctx, 0, buffersink_ctx, 0); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Error linking filters hwload--sink\n"); return false; } ret = avfilter_graph_config(filter_graph, nullptr); if (ret < 0) { av_log(nullptr, AV_LOG_ERROR, "Error configuring the filter graph\n"); return false; } ```
backuprepo 2025-12-23 10:34:01 +01:00
  • closed this issue
  • added the
    question
    label
Author
Owner

@nyanmisaka commented on GitHub (Dec 28, 2024):

You can refer to https://github.com/nyanmisaka/ffmpeg-rockchip/issues/141
Closing as it's not an issue.

@nyanmisaka commented on GitHub (Dec 28, 2024): You can refer to https://github.com/nyanmisaka/ffmpeg-rockchip/issues/141 Closing as it's not an issue.
Author
Owner

@qaz624824554 commented on GitHub (Dec 31, 2024):

@cnjswwxbtcc 老哥你解决了吗

@qaz624824554 commented on GitHub (Dec 31, 2024): @cnjswwxbtcc 老哥你解决了吗
Author
Owner

@qaz624824554 commented on GitHub (Jan 1, 2025):

硬啃1天ffmpeg源码后,终于解决了这个问题😭

@qaz624824554 commented on GitHub (Jan 1, 2025): 硬啃1天ffmpeg源码后,终于解决了这个问题😭
Author
Owner

@xqhua commented on GitHub (Jan 3, 2025):

@cnjswwxbtcc Bro, did you solve the problem? Can you share some details about the solution? Please.

@xqhua commented on GitHub (Jan 3, 2025): @cnjswwxbtcc Bro, did you solve the problem? Can you share some details about the solution? Please.
Author
Owner

@cnjswwxbtcc commented on GitHub (Jan 9, 2025):

硬啃1天ffmpeg源码后,终于解决了这个问题😭

可以分享下么, 我还没来得及搞这个, 最近有点其他的事忙

@cnjswwxbtcc commented on GitHub (Jan 9, 2025): > 硬啃1天ffmpeg源码后,终于解决了这个问题😭 可以分享下么, 我还没来得及搞这个, 最近有点其他的事忙
Author
Owner

@cnjswwxbtcc commented on GitHub (Jan 10, 2025):

@cnjswwxbtcc Bro, did you solve the problem? Can you share some details about the solution? Please.

Hi, Bro,
Maybe the filter can only init after av_read_frame(packet)
Refer to https://github.com/vivictorg/vivictpp,

// filter will be configured in this function 
vivictpp::libav::Frame vivictpp::libav::VideoFilter::filterFrame(const vivictpp::libav::Frame &inFrame)

and the following code will call this function:

void vivictpp::workers::DecoderWorker::readFrames(AVPacket *avPacket) {
    std::vector<vivictpp::libav::Frame> frames = decoder->handlePacket(avPacket);
    bool addFramesToQueue = false;
    for (auto frame : frames) {
        logger->debug("Got frame with pts={}, pkt_dts={}, keyframe={}",
                      frame->pts, frame->pkt_dts, vivictpp::libav::isKeyFrame(frame.avFrame()));
        dropFrameIfSeekingAndBufferFull();
        vivictpp::libav::Frame filtered = filter ? filter->filterFrame(frame) : frame;
        if (!filtered.empty()) {
            // If we start adding frames to queue, we ensure that all following frames are also put in queue
            // so they are not added to buffer out of order
            addFramesToQueue = addFramesToQueue || frameBuffer.isFull();
            if (addFramesToQueue) {
                frameQueue.push(filtered);
            } else {
                addFrameToBuffer(filtered);
            }
        }
    }
}

Below is the call stack of command ffmpeg -hwaccel rkmpp -hwaccel_output_format drm_prime -i input.mp4 -an -sn -vf scale_rkrga=w=720:h=480:format=yuv420p,hwdownload,format=yuv420p -f rawvideo - > /dev/null

#0  config_props (link=0x55be5e7310) at libavfilter/buffersrc.c:482
#1  0x000000558f7da990 in avfilter_config_links (filter=0x7f8c005c00) at libavfilter/avfilter.c:340
#2  0x000000558f7da974 in avfilter_config_links (filter=0x7f8c005dc0) at libavfilter/avfilter.c:329
#3  0x000000558f7da974 in avfilter_config_links (filter=0x7f8c005b20) at libavfilter/avfilter.c:329
#4  0x000000558f7da974 in avfilter_config_links (filter=0x7f8c005960) at libavfilter/avfilter.c:329
#5  0x000000558f7dec2c in graph_config_links (log_ctx=<optimized out>, graph=<optimized out>)
    at libavfilter/avfiltergraph.c:254
#6  avfilter_graph_config (graphctx=0x55be5ffc40, log_ctx=log_ctx@entry=0x0)
    at libavfilter/avfiltergraph.c:1177
#7  0x000000558f7b9e80 in configure_filtergraph (fg=fg@entry=0x55be5d3260)
    at fftools/ffmpeg_filter.c:1681
#8  0x000000558f7bba24 in ifilter_send_frame (ifilter=0x55be5d8710, frame=frame@entry=0x55be598810,
    keep_reference=0) at fftools/ffmpeg_filter.c:2416
#9  0x000000558f7aeff4 in send_frame_to_filters (decoded_frame=<optimized out>, ist=<optimized out>)
    at fftools/ffmpeg_dec.c:153
#10 dec_packet (ist=0x7f8c0046a0, pkt=<optimized out>, no_eof=<optimized out>)
    at fftools/ffmpeg_dec.c:813
#11 0x000000558f7d545c in process_input_packet (ist=0x7f8c0046a0, pkt=0x7f8c004d50, no_eof=0)
    at fftools/ffmpeg.c:811
#12 0x000000558f7ad04c in process_input (file_index=<optimized out>) at fftools/ffmpeg.c:1115
#13 transcode_step (ost=0x55be5caaf0) at fftools/ffmpeg.c:1142
#14 transcode (err_rate_exceeded=<synthetic pointer>) at fftools/ffmpeg.c:1204
#15 main (argc=<optimized out>, argv=<optimized out>) at fftools/ffmpeg.c:1330
@cnjswwxbtcc commented on GitHub (Jan 10, 2025): > @cnjswwxbtcc Bro, did you solve the problem? Can you share some details about the solution? Please. Hi, Bro, Maybe the filter can only init after `av_read_frame(packet)` Refer to `https://github.com/vivictorg/vivictpp`, ``` // filter will be configured in this function vivictpp::libav::Frame vivictpp::libav::VideoFilter::filterFrame(const vivictpp::libav::Frame &inFrame) ``` and the following code will call this function: ``` void vivictpp::workers::DecoderWorker::readFrames(AVPacket *avPacket) { std::vector<vivictpp::libav::Frame> frames = decoder->handlePacket(avPacket); bool addFramesToQueue = false; for (auto frame : frames) { logger->debug("Got frame with pts={}, pkt_dts={}, keyframe={}", frame->pts, frame->pkt_dts, vivictpp::libav::isKeyFrame(frame.avFrame())); dropFrameIfSeekingAndBufferFull(); vivictpp::libav::Frame filtered = filter ? filter->filterFrame(frame) : frame; if (!filtered.empty()) { // If we start adding frames to queue, we ensure that all following frames are also put in queue // so they are not added to buffer out of order addFramesToQueue = addFramesToQueue || frameBuffer.isFull(); if (addFramesToQueue) { frameQueue.push(filtered); } else { addFrameToBuffer(filtered); } } } } ``` Below is the call stack of command `ffmpeg -hwaccel rkmpp -hwaccel_output_format drm_prime -i input.mp4 -an -sn -vf scale_rkrga=w=720:h=480:format=yuv420p,hwdownload,format=yuv420p -f rawvideo - > /dev/null` ``` #0 config_props (link=0x55be5e7310) at libavfilter/buffersrc.c:482 #1 0x000000558f7da990 in avfilter_config_links (filter=0x7f8c005c00) at libavfilter/avfilter.c:340 #2 0x000000558f7da974 in avfilter_config_links (filter=0x7f8c005dc0) at libavfilter/avfilter.c:329 #3 0x000000558f7da974 in avfilter_config_links (filter=0x7f8c005b20) at libavfilter/avfilter.c:329 #4 0x000000558f7da974 in avfilter_config_links (filter=0x7f8c005960) at libavfilter/avfilter.c:329 #5 0x000000558f7dec2c in graph_config_links (log_ctx=<optimized out>, graph=<optimized out>) at libavfilter/avfiltergraph.c:254 #6 avfilter_graph_config (graphctx=0x55be5ffc40, log_ctx=log_ctx@entry=0x0) at libavfilter/avfiltergraph.c:1177 #7 0x000000558f7b9e80 in configure_filtergraph (fg=fg@entry=0x55be5d3260) at fftools/ffmpeg_filter.c:1681 #8 0x000000558f7bba24 in ifilter_send_frame (ifilter=0x55be5d8710, frame=frame@entry=0x55be598810, keep_reference=0) at fftools/ffmpeg_filter.c:2416 #9 0x000000558f7aeff4 in send_frame_to_filters (decoded_frame=<optimized out>, ist=<optimized out>) at fftools/ffmpeg_dec.c:153 #10 dec_packet (ist=0x7f8c0046a0, pkt=<optimized out>, no_eof=<optimized out>) at fftools/ffmpeg_dec.c:813 #11 0x000000558f7d545c in process_input_packet (ist=0x7f8c0046a0, pkt=0x7f8c004d50, no_eof=0) at fftools/ffmpeg.c:811 #12 0x000000558f7ad04c in process_input (file_index=<optimized out>) at fftools/ffmpeg.c:1115 #13 transcode_step (ost=0x55be5caaf0) at fftools/ffmpeg.c:1142 #14 transcode (err_rate_exceeded=<synthetic pointer>) at fftools/ffmpeg.c:1204 #15 main (argc=<optimized out>, argv=<optimized out>) at fftools/ffmpeg.c:1330 ```
Author
Owner

@qaz624824554 commented on GitHub (Jan 13, 2025):

硬啃1天ffmpeg源码后,终于解决了这个问题😭

可以分享下么, 我还没来得及搞这个, 最近有点其他的事忙

我写了篇博客,可以参考下

@qaz624824554 commented on GitHub (Jan 13, 2025): > > 硬啃1天ffmpeg源码后,终于解决了这个问题😭 > > 可以分享下么, 我还没来得及搞这个, 最近有点其他的事忙 我写了篇博客,可以[参考下](https://blog.csdn.net/Leon_Chenl/article/details/145105042?spm=1001.2014.3001.5501)
Author
Owner

@cnjswwxbtcc commented on GitHub (Feb 27, 2025):

You can refer to #141 Closing as it's not an issue.

我参考了vivictpp, 它的实现是从frmae里面获取hw_frames_ctx, 我不太明白为什么可以这么做, 每个frame的hw_frmaes_ctx我打印出来地址并不相同, 为何不需要重复的初始化这个buffersrc?

vivictpp::libav::Frame vivictpp::libav::VideoFilter::filterFrame(const vivictpp::libav::Frame &inFrame) {
  if (inFrame.avFrame()->format != formatParameters.pixelFormat || reconfigure) {
    reconfigure = false;
    AVPixelFormat newFormat = (AVPixelFormat) inFrame.avFrame()->format;
    spdlog::info("Reconfiguring filter, pixel format changed from {} to {}", av_get_pix_fmt_name(formatParameters.pixelFormat), av_get_pix_fmt_name(newFormat));
    formatParameters.pixelFormat = newFormat;
    formatParameters.hwFramesContext = inFrame.avFrame()->hw_frames_ctx;
    configure();
  }
  return Filter::filterFrame(inFrame);
}
@cnjswwxbtcc commented on GitHub (Feb 27, 2025): > You can refer to [#141](https://github.com/nyanmisaka/ffmpeg-rockchip/issues/141) Closing as it's not an issue. 我参考了vivictpp, 它的实现是从frmae里面获取`hw_frames_ctx`, 我不太明白为什么可以这么做, 每个frame的`hw_frmaes_ctx`我打印出来地址并不相同, 为何不需要重复的初始化这个buffersrc? ```cpp vivictpp::libav::Frame vivictpp::libav::VideoFilter::filterFrame(const vivictpp::libav::Frame &inFrame) { if (inFrame.avFrame()->format != formatParameters.pixelFormat || reconfigure) { reconfigure = false; AVPixelFormat newFormat = (AVPixelFormat) inFrame.avFrame()->format; spdlog::info("Reconfiguring filter, pixel format changed from {} to {}", av_get_pix_fmt_name(formatParameters.pixelFormat), av_get_pix_fmt_name(newFormat)); formatParameters.pixelFormat = newFormat; formatParameters.hwFramesContext = inFrame.avFrame()->hw_frames_ctx; configure(); } return Filter::filterFrame(inFrame); } ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: starred/ffmpeg-rockchip#137
No description provided.