web-dev-qa-db-ja.com

C ++のffmpeghwaccelを使用

Ffmpegでハードウェアアクセラレーションを使用してファイルをデコードするにはどうすればよいですか?

私はffmpegを使用する動作するビデオプレーヤーを書きました。 "av_hwaccel_next"を使用してサポートを確認し、mpeg2_dxvaを見つけました。

ただし、(通常どおり)mpeg2ファイルをロードすると、ハードウェアアクセラレーションが得られません。 AVCodecContext->hwaccelAVCodecContext->hwaccelcontextは両方ともnullです。

ハードウェアアクセラレーションを有効にするには、どこかにフラグを渡す必要がありますか?

私はこれに関する情報を見つけることができませんでした、誰かが良い情報源を知っていますか?

20
ronag

Ffmpegのドキュメントを読むことから始めましょう: https://trac.ffmpeg.org/wiki/HWAccelIntro そしてより良い答え ffmpegでハードウェアアクセラレーションを使用する方法 (そしてLinuxのチェックページ- https://wiki.archlinux.org/index.php/Hardware_video_acceleration

FFmpegツールを使用する場合、HW支援デコードは_-hwaccel_オプションを使用して有効になり、特定のデコーダーが有効になります。各デコーダーには特定の制限がある場合があります(たとえば、H.264デコーダーはベースラインプロファイルのみをサポートする場合があります)。 HW支援エンコーディングは、特定のエンコーダー(h264_nvencなど)を使用して有効にします。 HW支援処理のフィルタリングは、いくつかのフィルターでのみサポートされています..いくつかのハードウェアアクセラレーション標準APIがあり、そのうちのいくつかはFFmpegによってある程度サポートされています

hwaccelのアクティブ化は次のようなコードによって制御されました(2013年以降にビットが再フォーマットされました https://github.com/FFmpeg/FFmpeg/commit/08303d774132775d49d4ba767092de5d426f089d

_avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt);
_

たとえば、libavcodec/mpeg12dec.c https://github.com/FFmpeg/FFmpeg/blob/6c7254722ad43712db5686feee8bf75c74d8635b/libavcodec/mpeg12dec.c

_avctx->pix_fmt = mpeg_get_pixelformat(avctx);
avctx->hwaccel = ff_find_hwaccel(avctx->codec->id, avctx->pix_fmt);
_

_ff_find_hwaccel_は、画像と使用可能なすべてのhwacceleratorのコーデックとpixelformatのペアをチェックします。

_AVHWAccel *ff_find_hwaccel(enum CodecID codec_id, enum PixelFormat pix_fmt)
{
    AVHWAccel *hwaccel=NULL;

    while((hwaccel= av_hwaccel_next(hwaccel))){
        if (   hwaccel->id      == codec_id
            && hwaccel->pix_fmt == pix_fmt)
            return hwaccel;
    }
    return NULL;
}
_

たとえば、dxva2( https://en.wikipedia.org/wiki/DirectX_Video_Acceleration )には次のものがあります。

_AVHWAccel mpeg2_dxva2_hwaccel = {
    .name           = "mpeg2_dxva2",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_MPEG2VIDEO,
    .pix_fmt        = PIX_FMT_DXVA2_VLD,
    .capabilities   = 0,
    .start_frame    = start_frame,
    .decode_slice   = decode_slice,
    .end_frame      = end_frame,
    .priv_data_size = sizeof(struct dxva2_picture_context),
};
_

そして_libavutil/pixfmt.h_は、サポートされているすべてのハードウェアデコーダー/アクセラレーターをピクセル形式で一覧表示します https://ffmpeg.org/doxygen/3.2/pixfmt_8h.html

_AV_PIX_FMT_XVMC_MPEG2_MC    - XVideo Motion Acceleration via common packet passing.
AV_PIX_FMT_XVMC_MPEG2_IDCT  - undocumented
AV_PIX_FMT_XVMC         - undocumented
AV_PIX_FMT_VDPAU_H264   - H.264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_MPEG1  - MPEG-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_MPEG2  - MPEG-2 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_WMV3   - WMV3 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_VDPAU_VC1    - VC-1 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers. 
AV_PIX_FMT_VAAPI_MOCO   - HW acceleration through VA API at motion compensation entry-point, Picture.data[3] contains a vaapi_render_state struct which contains macroblocks as well as various fields extracted from headers.
AV_PIX_FMT_VAAPI_IDCT   - HW acceleration through VA API at IDCT entry-point, Picture.data[3] contains a vaapi_render_state struct which contains fields extracted from headers.
AV_PIX_FMT_VAAPI_VLD    - HW decoding through VA API, Picture.data[3] contains a VASurfaceID. 
AV_PIX_FMT_VDPAU_MPEG4  - MPEG-4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers.
AV_PIX_FMT_DXVA2_VLD    - HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer. 
AV_PIX_FMT_VDPAU        - HW acceleration through VDPAU, Picture.data[3] contains a VdpVideoSurface. 
AV_PIX_FMT_VDA          - HW acceleration through VDA, data[3] contains a CVPixelBufferRef. 
AV_PIX_FMT_QSV          - HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
AV_PIX_FMT_MMAL         - HW acceleration though MMAL, data[3] contains a pointer to the MMAL_BUFFER_HEADER_T structure.
AV_PIX_FMT_D3D11VA_VLD  - HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer.
AV_PIX_FMT_CUDA         - HW acceleration through CUDA. data[i] contain CUdeviceptr pointers exactly as for system memory frames. 
_

ピクセル形式の実際の選択は、mpeg1/2の_ff_find_hwaccel_の_libavcodec/mpeg12dec.c_、static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)の前に呼び出される関数で行われます。以前のバージョンのffmpeg/libavcodecでは、_avctx->xvmc_acceleration_および/または_avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU_をチェックするか、avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420);を呼び出してhwデコードを有効にする場合があります。

最近のバージョン(2017)では、それといくつかの近くの関数がhwコーダーの選択を行います https://github.com/FFmpeg/FFmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#L1189

基本的に:ハードウェアデコーダーとそのAPI(廃止 [〜#〜] xvmc [〜#〜][〜#〜] vdpau [〜#〜]VA API 、MS [〜#〜] dxva [〜#〜] またはMS Direct3D11 、またはvideotoolbox)は、ffmpegのビルドで有効にする必要があります- ハードウェアでサポートされています およびそのドライバー/ライブラリ(多くはプロプライエタリであり、個別にダウンロードする必要があります)。場合によっては、_-hwaccel_オプションをffmpegに指定するか、プラグインをロードする必要があります。 Linuxでは、vainfoおよびvdpauinfoコマンドを使用して、最も一般的な標準のビデオハードウェアデコードAPIで可用性とサポートされているプロファイルをテストできます。

入力ファイル(mpeg1/2の場合)はグレースケールではなく、_s->chroma_format_ 2未満(4:2:0 クロマサブサンプリング )である必要があります。これはISO/IECMPEGおよびITUでは通常です。 -T VCEGH.26x;ただし一部のMPEG-4パート2ではなく、H.264/MPEG-4 AVCの高4:4:4バリアントではない)。

_static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
#if CONFIG_MPEG2_XVMC_HWACCEL
    AV_PIX_FMT_XVMC,
#endif
#if CONFIG_MPEG_VDPAU_DECODER && FF_API_VDPAU
    AV_PIX_FMT_VDPAU_MPEG2,
#endif
#if CONFIG_MPEG2_VDPAU_HWACCEL
    AV_PIX_FMT_VDPAU,
#endif
#if CONFIG_MPEG2_DXVA2_HWACCEL
    AV_PIX_FMT_DXVA2_VLD,
#endif
#if CONFIG_MPEG2_D3D11VA_HWACCEL
    AV_PIX_FMT_D3D11VA_VLD,
#endif
#if CONFIG_MPEG2_VAAPI_HWACCEL
    AV_PIX_FMT_VAAPI,
#endif
#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
    AV_PIX_FMT_VIDEOTOOLBOX,
#endif
    AV_PIX_FMT_YUV420P,
    AV_PIX_FMT_NONE
};

static const enum AVPixelFormat mpeg12_pixfmt_list_422[] = {
    AV_PIX_FMT_YUV422P,
    AV_PIX_FMT_NONE
};

static const enum AVPixelFormat mpeg12_pixfmt_list_444[] = {
    AV_PIX_FMT_YUV444P,
    AV_PIX_FMT_NONE
};

#if FF_API_VDPAU
static inline int uses_vdpau(AVCodecContext *avctx) {
    return avctx->pix_fmt == AV_PIX_FMT_VDPAU_MPEG1 || avctx->pix_fmt == AV_PIX_FMT_VDPAU_MPEG2;
}
#endif

static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)
{
    Mpeg1Context *s1  = avctx->priv_data;
    MpegEncContext *s = &s1->mpeg_enc_ctx;
    const enum AVPixelFormat *pix_fmts;

    if (CONFIG_GRAY && (avctx->flags & AV_CODEC_FLAG_GRAY))
        return AV_PIX_FMT_GRAY8;

    if (s->chroma_format < 2)
        pix_fmts = avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO ?
                                mpeg1_hwaccel_pixfmt_list_420 :
                                mpeg2_hwaccel_pixfmt_list_420;
    else if (s->chroma_format == 2)
        pix_fmts = mpeg12_pixfmt_list_422;
    else
        pix_fmts = mpeg12_pixfmt_list_444;

    return ff_thread_get_format(avctx, pix_fmts);
}

static void setup_hwaccel_for_pixfmt(AVCodecContext *avctx)
{
    // until then pix_fmt may be changed right after codec init
    if (avctx->hwaccel
#if FF_API_VDPAU
        || uses_vdpau(avctx)
#endif
        )
        if (avctx->idct_algo == FF_IDCT_AUTO)
            avctx->idct_algo = FF_IDCT_SIMPLE;

    if (avctx->hwaccel && avctx->pix_fmt == AV_PIX_FMT_XVMC) {
        Mpeg1Context *s1 = avctx->priv_data;
        MpegEncContext *s = &s1->mpeg_enc_ctx;

        s->pack_pblocks = 1;
#if FF_API_XVMC
FF_DISABLE_DEPRECATION_WARNINGS
        avctx->xvmc_acceleration = 2;
FF_ENABLE_DEPRECATION_WARNINGS
#endif /* FF_API_XVMC */
    }
}
_
24
osgx