Question

Comment décoder un fichier avec une accélération matérielle avec FFMPEG?

J'ai écrit un lecteur vidéo fonctionnel qui utilise FFMPEG. J'ai vérifié le soutien en utilisant "av_hwaccel_next" et trouvé mpeg2_dxva.

Cependant, lorsque je charge un fichier MPEG2 (comme d'habitude), je n'obtiens aucune accélération matérielle. AVCodecContext->hwaccel et AVCodecContext->hwaccelcontext sont tous les deux nuls.

Dois-je passer un drapeau quelque part pour activer l'accélération HW?

Je n'ai pas pu trouver d'informations à ce sujet, quelqu'un connaît une bonne source?

Était-ce utile?

La solution

Commencez par la lecture de la documentation FFMPEG: https://trac.ffmpeg.org/wiki/hwaccelintro et mieux répondre Comment utiliser l'accélération matérielle avec FFMPEG (et pour la page de vérification Linux https://wiki.archlinux.org/index.php/hardware_video_acceleration)

Lorsque vous utilisez FFMPEG l'outil, le décodage assisté par HW est activé à l'aide du -hwaccel Option, qui permet un décodeur spécifique. Chaque décodeur peut avoir des limitations spécifiques (par exemple, un décodeur H.264 ne peut prendre en charge que le profil de base). Le codage assisté par HW est activé via l'utilisation d'un encodeur spécifique (par exemple H264_NVENC). Le filtrage du traitement assisté par HW n'est pris en charge que dans quelques filtres. Il existe plusieurs API de normes d'accélération matérielle, dont certains sont soutenus dans une certaine mesure par ffmpeg.

L'activation de Hwaccel a été contrôlée par le code comme (bit reformaté après 2013 https://github.com/ffmpeg/ffmpeg/commit/08303d774132775d49d4ba767092de5d426f089d)

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

Par exemple, dans libavcodec / mpeg12dec.c https://github.com/ffmpeg/ffmpeg/blob/6c7254722ad43712db5686feee8bf75c74d8635b/libavcodec/mpeg12dec.c.c

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

La ff_find_hwaccel Vérifie le codec et la paire d'images Pixelformat et de tous les hwaccelerators disponibles.

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;
}

Par exemple, dxva2 (https://en.wikipedia.org/wiki/directx_video_acceleration) a:

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),
};

Et libavutil/pixfmt.h Énumére tous les décodeurs / accélérateurs HW pris en charge par leurs formats de pixels 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. 

La sélection réelle des formats de pixels est en fonction appelée précédemment ff_find_hwaccel, la static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) de libavcodec/mpeg12dec.c Pour MPEG1 / 2. Dans les versions antérieures de FFMPEG / LIBAVCODEC, il vérifie avctx->xvmc_acceleration et / ou avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU ou appels avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420); pour permettre le décodage HW dans certains cas.

Dans la version récente (2017), l'informatique et plusieurs fonctions voisines font la sélection de HW Coder https://github.com/ffmpeg/ffmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#l1189.

Fondamentalement: le décodeur matériel et son API (obsolète Xvmc, Vdpau, API VA, MME Dxva ou ms Direct3d11, ou videotoolbox) doit être activé dans votre construction de ffmpeg et Prend en charge par votre matériel et ses pilotes / bibliothèques (beaucoup sont propriétaires et doivent être téléchargés séparément). quelquefois -hwaccel L'option doit être donnée à FFMPEG ou à plugin chargé. Dans Linux, vous pouvez utiliser vainfo et vdpauinfo Commandes pour tester la disponibilité et les profils pris en charge avec des API de décodage vidéo standard HW standard les plus populaires.

Le fichier d'entrée (pour MPEG1 / 2) ne doit pas être en niveaux de gris, il devrait avoir s->chroma_format Moins de 2 (4: 2: 0 Sous-échantillonnage de chrome, qui est habituel pour ISO / IEC MPEG et ITU-T VCEG H.26X; mais pas pour certains MPEG-4 partie 2 et non pour les variantes élevées 4: 4: 4 de H.264 / MPEG-4 AVC).

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 */
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top