微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

硬件解码视频 C++ 时出现 FFmpeg 错误

如何解决硬件解码视频 C++ 时出现 FFmpeg 错误

我正在尝试在 c ++ 中的 ffmpeg 中找出硬件解码。我在任何 api 上都会遇到相同的错误。 这是初始化代码


    AVHWDeviceType devType = av_hwdevice_find_type_by_name(HW_DECODER_NAME);

    for (int i = 0;; i++)
    {
        const AVCodecHWConfig *config = avcodec_get_hw_config(av_codec,i);
        if (!config)
        {
            fprintf(stderr,"Decoder %s does not support device type %s.\n",av_codec->name,av_hwdevice_get_type_name(devType));
            return false;
        }

        if (config->methods & AV_CODEC_HW_CONfig_METHOD_HW_DEVICE_CTX && config->device_type == devType)
        {
            hw_pix_fmt = config->pix_fmt;
            break;
        }
    }

    hw_device_ctx = av_hwdevice_ctx_alloc(devType);

    *av_codec_ctx = avcodec_alloc_context3(av_codec);
    if (!av_codec_ctx)
    {
        printf("Couldn't create AVCodecContext\n");
        return false;
    }

    if (avcodec_parameters_to_context(*av_codec_ctx,av_codec_params) < 0)
    {
        printf("Couldn't initialize AVCodecContext\n");
        return false;
    }

    (*av_codec_ctx)->get_format  = get_hw_format;

    //Initialize hardware context
    int err = 0;
    if ((err = av_hwdevice_ctx_create(&hw_device_ctx,devType,NULL,0)) < 0)
    {
        fprintf(stderr,"Failed to create specified HW device.\n");
        return false;
    }

    (*av_codec_ctx)->hw_device_ctx = av_buffer_ref(hw_device_ctx);

    if (avcodec_open2(*av_codec_ctx,av_codec,NULL) < 0)
    {
        printf("Couldn't open codec\n");
        return false;
    }

    b_is_initialized = true;

这里是解码器代码

int response;

    response = avcodec_send_packet(av_codec_ctx,av_packet);
    if (response < 0)
    {
        printf("Couldn't send video frame to decoder.\n");
        print_error(response);
        return false;
    }

    realloc_frame(&av_frame);

    response = avcodec_receive_frame(av_codec_ctx,av_frame);
    if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
    {
        av_frame_free(&av_frame);
        return false;
    }
    else if (response < 0)
    {
        print_error(response);
        return false;
    }

    if(hwdecoder.is_initialized())
    {
        if(!hwdecoder.decode(av_packet,&av_frame))
        {
            printf("Failed while decoding frame on gpu.\n");
        }
    }

    pts = av_frame->pts;

    // Set up sws scaler
    if (!sws_scaler_ctx)
    {
        auto source_pix_fmt = correct_for_deprecated_pixel_format((AVPixelFormat)av_frame->format);
        //Send here frame params
        sws_scaler_ctx = sws_getContext(width,height,source_pix_fmt,width,AV_PIX_FMT_RGB0,SWS_BICUBIC,NULL);

在处理器上解码没有问题,但是当我在 gpu 上解码时,结果是解码了视频的某些部分,然后在 avcodec_send_packet 期间我得到了Invalid data found处理输入错误时。请帮忙,我已经受苦了第二周。

编辑

OP 忘记了 hwdecoder.decode 方法

int ret = 0; 
realloc_frame(&sw_frame);      
if ((*av_frame)->format == hw_pix_fmt)
{         
  if ((ret = av_hwframe_transfer_data(sw_frame,*av_frame,0)) < 0)          
  {             
     fprintf(stderr,"Error transferring the data to system memory\n");               
     av_frame_free(&sw_frame);             
     return false;         
  } 
} 

错误日志:

Couldn't send video frame to decoder.
Invalid data found when processing input
[AVHWFramesContext @ 000001E44F6EC8C0] Static surface pool size exceeded.
[h264 @ 000001E445D60940] get_buffer() Failed
[h264 @ 000001E445D60940] thread_get_buffer() Failed
[h264 @ 000001E445D60940] decode_slice_header error
[h264 @ 000001E445D60940] no frame!

我的代码基于这个例子:https://ffmpeg.org/doxygen/4.0/hw_decode_8c-example.html

在 windows 上我使用 dxva2 设备,使用 cmake 3.9 配置项目,并使用 MSVC amd64 构建。 在 linux 上,我使用了 vdpau 设备,从源 ffmpeg 库编译,项目使用 cmake 3.9 配置并使用 gcc 10 构建

更新

代码在 cuda 上运行良好,但对于另一个 api,我仍然遇到问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。