Libavcodec (FFMPEG) D3D11 硬件加速不输出硬件帧

问题描述 投票:0回答:0

问题

我正在尝试让 FFMPEG 将 D3D11 2D 纹理直接输出为帧。据我了解,这实际上是可能的。这样做的原因是,我可以直接在 GPU 上解码 YUV 格式,然后显示它,而无需将其编组回 CPU。

我的问题是我无法让解码器以所需格式实际输出帧,它们始终是软件

YUV420J
.

这是因为我没有正确初始化解码器吗?或者我可能还缺少其他一些配置。


详情

我大部分时间都在关注example,有一些细微差别:

  1. 我只需要处理一种格式,原始 h264,所以我手动配置解码器以使用
    AV_CODEC_ID_H264
  2. 我已经准备好初始化 D3DDevice 和 Context,所以我在
    av_hwdevice_ctx_init
    上使用
    av_hwdevice_ctx_create
    。 (我试过只使用
    av_hwdevice_ctx_create
    并得到相同的结果)
  3. 前面说了,我不想用
    av_hwframe_transfer_data
    ,因为我想把数据保存在GPU上作为纹理,马上显示出来

这是我的初始化代码:

    AVHWDeviceType type = AV_HWDEVICE_TYPE_D3D11VA;

    hw_pix_fmt = AV_PIX_FMT_D3D11;

    _codec = avcodec_find_decoder(AV_CODEC_ID_H264); // NOT SURE IF THIS IS THE HW SUPPORTED FMT
    
    int i;
    for (i = 0;; i++) {
        const AVCodecHWConfig* config = avcodec_get_hw_config(_codec, i);
        if (!config) {
            fprintf(stderr, "Decoder %s does not support device type %s.\n",
                _codec->name, av_hwdevice_get_type_name(type));
            return;
        }
        if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
            config->device_type == type) {
            hw_pix_fmt = config->pix_fmt;
            break;
        }
    }

    if (!(_codecCtx = avcodec_alloc_context3(_codec))) {
        // ERROR!
        return;
    }

    _hw_device_ctx = av_hwdevice_ctx_alloc(type);

    _device_ctx = reinterpret_cast<AVHWDeviceContext*>(_hw_device_ctx->data);
    _d3d11va_device_ctx = reinterpret_cast<AVD3D11VADeviceContext*>(_device_ctx->hwctx);
    _d3d11va_device_ctx->device = dev;

    _codecCtx->hw_device_ctx = av_buffer_ref(_hw_device_ctx);


    if (av_hwdevice_ctx_init(_codecCtx->hw_device_ctx) < 0) {
        return;
    }


    if (avcodec_open2(_codecCtx, _codec, NULL) < 0) {
        return;
    }

    _parser = av_parser_init(_codec->id);
    _packet = av_packet_alloc();

我正在做标准的事情来解码,并且知道它有效,因为我已经很好地使用了软件解码,但无论如何:

void Decoder::Load(std::vector<std::byte> data) {
    int data_size = data.size();

    int bytesRead = 0;
    int bytesParsed = 0;

    while (data_size > 0) {
        bytesParsed = av_parser_parse2(
            _parser,
            _codecCtx,
            &_packet->data,
            &_packet->size,
            (uint8_t*)&data[bytesRead],
            data.size() - bytesRead,
            AV_NOPTS_VALUE,
            AV_NOPTS_VALUE,
            0);

        bytesRead += bytesParsed;
        data_size -= bytesParsed;

        if (bytesParsed < 0) {
            //std::cout << "Error while parsing packet" << std::endl;
            return;
        }

        if (_packet->size) {
            int ret = avcodec_send_packet(_codecCtx, _packet);
            if (ret < 0) {
                //std::cout << "Error Sending Packet for Decoding" << std::endl;
                return;
            }

            while (ret >= 0) {
                AVFrame* frame = av_frame_alloc();
                ret = avcodec_receive_frame(_codecCtx, frame);

                if (frame->format != AV_PIX_FMT_D3D11) { // <--- THIS NEVER EVALUATES AS FALSE, IT'S ALWAYS THE YUV420J FORMAT, NOT THE HARDWARE FORMAT
                    break;
                }

                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                }
                else if (ret < 0) {
                    //std::cout << "Error During Decoding" << std::endl;
                    return;
                }

                _frameQueue.push(frame);
            }
        }
    }
}

我如何构建 FFMPEG:

./../../sources/ffmpeg/configure \
             --prefix=./../../installed \
             --toolchain=msvc \
             --arch=x86_64 \
             --enable-yasm  \
             --enable-asm \
             --enable-shared \
             --enable-dxva2 \
             --enable-d3d11va \
             --disable-static \
             --enable-gpl \
             --extra-ldflags="-LIBPATH:./../../installed/lib/" \
             --extra-cflags="-I./../../installed/include/"
windows ffmpeg h.264 direct3d libavcodec
© www.soinside.com 2019 - 2024. All rights reserved.