zoukankan      html  css  js  c++  java
  • 【GPU编解码】GPU硬解码---DXVA (转)

    前面介绍利用NVIDIA公司提供的CUVID库进行视频硬解码,下面将介绍利用DXVA进行硬解码。

    一、DXVA介绍

      DXVA是微软公司专门定制的视频加速规范,是一种接口规范。DXVA规范制定硬件加速解码可分四级:VLD,控制BitStream;IDCT,反余弦变换;Mocomp,运动补偿,Pixel Prediction;PostProc,显示后处理。其中,VLD加速等级最高,所以其包含IDCT、MoCoopm和PostProc;IDCT加速次之,包含MoCoopm和PostProc;最后MoComp加速仅包含PostProc。一款显卡芯片在硬件支持DXVA规范,并不代表它就实现了DXVA所有功能。DXVA_Checker可用于检测硬件所支持的等级,DXVA_Checker运行示意图如下所示。

    二、使用FFmpeg中DXVA技术硬解码

    基本思路:

    1.根据FFmpeg对编码器的描述,实现自定义的硬解码器。

    2.通过REGISTER_ENCODEC(X,x)将自定义的视频编码器添加到视频编解码器。

    3.在视频解码,根据编码器ID或编码器名称找到视频编解码器中自定义的视频解码器。

    4.利用自定义的视频解码器,解码视频。

    其关键步骤是:自定义解码器的实现,需要参考FFmpeg源码中,解码器的定义和接口设计。

    基于DXVA的自定义解码器实现

    1.熟悉FFmpeg中编解码的组织方式

    下图是ffmpeg编解码组织的简单示意图。

    由示意图可知,编解码器由全局链表组织,可根据编码器的名称或ID,获取编解码器。

    编解码器的具体编解码的具体工作,由编解码器定义的函数指针完成。

    自定义解码器时,需要按照AVCodec结构体,定义解码器的属性,然后注册到全局编解码器链表中。

    2.基于DXVA解码器的定义实现

    ff_h264_dxva2_decoder的定义如下:

    复制代码

     1 AVCodec ff_h264_dxva2_decoder = {
     2     .name           = "h264_dxva2",
     3     .type           = AVMEDIA_TYPE_VIDEO,
     4     .id             = AV_CODEC_ID_H264,
     5     .priv_data_size = sizeof(DXVA2_DecoderContext),
     6     .init           = h264_dxva2dec_init,
     7     .close          = h264_dxva2dec_close,
     8     .decode         = h264_dxva2dec_decode,
     9     .capabilities   = CODEC_CAP_DELAY,
    10     .flush          = h264_dxva2dec_flush,
    11     .long_name      = NULL_IF_CONFIG_SMALL("H.264 (DXVA2 acceleration)"),
    12 };

    复制代码

    ff_h264_dxva2_decoder的函数指针对应的函数定义如下:

    复制代码

     1 static int h264_dxva2dec_decode(AVCodecContext *avctx, void *data, int *got_frame,
     2                                   AVPacket *avpkt)
     3 {
     4     return ff_dxva2dec_decode(avctx,data,got_frame,avpkt,&ff_h264_decoder);
     5 }
     6 
     7 static av_cold int h264_dxva2dec_close(AVCodecContext *avctx)
     8 {
     9     return ff_dxva2dec_close(avctx,&ff_h264_decoder);
    10 }
    11 
    12 static av_cold int h264_dxva2dec_init(AVCodecContext *avctx)
    13 {
    14     return ff_dxva2dec_init(avctx,&ff_h264_dxva2_decoder,&ff_h264_decoder);
    15 }
    16 
    17 static void h264_dxva2dec_flush(AVCodecContext *avctx)
    18 {
    19     ff_dxva2dec_flush(avctx,&ff_h264_decoder);
    20 }

    复制代码

    上述代码,只是ff_dxva2dec_init(),ff_dxva2dec_flush(),ff_dxva2dec_decode(),ff_dxva2dec_close()的封装,具体解码的实现,由ff_dxva2dec_xxx相关函数完成,其代码实现如下:

    View Code

    其中,在ff_dxva2dec_init()函数中,利用av_create_dxva2()函数创建dxva2_context,av_setup_dxva2()设置dxva2_context。

    在ff_dxva2dec_close()函数中,利用av_release_dxva2()释放dxva2_context。

    av_xxx_dxva2()相关函数,主要利用DXVA2的API接口,创建dxva2的上下文,并进行管理。

    总体而言,经过四次封装,形成方便的硬解码接口。

    DXVA2 API接口 ---> av_xxx_dxva2 ---> ff_dxva2dec_xxx ---> h264_dxva2dec_xxx ---> ff_h264_dxva2_decoder

    参考资料:

    http://web.archiveorange.com/archive/v/4q4BhNz4oevWmMtHL3eY

  • 相关阅读:
    [笔记] 辛普森积分
    Luogu P4175 [CTSC2008]网络管理
    Luogu P4331 [BOI2004]Sequence 数字序列
    Luogu P1456 Monkey King
    Luogu P3261 [JLOI2015]城池攻占
    Luogu P4309 [TJOI2013]最长上升子序列
    Luogu P4246 [SHOI2008]堵塞的交通
    Luogu P3638 [APIO2013]机器人
    Luogu P4294 [WC2008]游览计划
    CF613D Kingdom and its Cities
  • 原文地址:https://www.cnblogs.com/xmphoenix/p/4508428.html
Copyright © 2011-2022 走看看