23 Stimmen

ffmpeg hwaccel von C++ aus verwenden

Wie dekodiere ich eine Datei mit Hardwarebeschleunigung mit ffmpeg?

Ich habe einen funktionierenden Videoplayer geschrieben, der ffmpeg verwendet. Ich habe die Unterstützung überprüft, indem ich "av_hwaccel_next" und fand mpeg2_dxva .

Wenn ich jedoch eine mpeg2-Datei lade (wie üblich), erhalte ich keine Hardware-Beschleunigung. AVCodecContext->hwaccel y AVCodecContext->hwaccelcontext sind beide null.

Muss ich irgendwo ein Kennzeichen angeben, um die hw-Beschleunigung zu aktivieren?

Ich habe dazu keine Informationen gefunden. Kennt jemand eine gute Quelle?

29voto

osgx Punkte 85299

Beginnen Sie mit dem Lesen der ffmpeg-Dokumentation: https://trac.ffmpeg.org/wiki/HWAccelIntro und bessere Antwort Wie man die Hardware-Beschleunigung mit ffmpeg verwendet (und für Linux siehe Seite https://wiki.archlinux.org/index.php/Hardware_video_acceleration )

Bei der Verwendung des Tools FFmpeg wird die HW-gestützte Dekodierung über die Option -hwaccel Option, die einen bestimmten Decoder aktiviert. Jeder Decoder kann bestimmte Einschränkungen haben (z. B. kann ein H.264-Decoder nur das Baseline-Profil unterstützen). Die HW-unterstützte Kodierung wird durch die Verwendung eines bestimmten Encoders (z. B. h264_nvenc) aktiviert. Filterung Die HW-unterstützte Verarbeitung wird nur in einigen wenigen Filtern unterstützt. Es gibt mehrere Hardware-Beschleunigungsstandards API, von denen einige unterstützt werden bis zu einem gewissen Grad durch FFmpeg.

hwaccel-Aktivierung wurde durch Code wie (Bit nach 2013 neu formatiert https://github.com/FFmpeg/FFmpeg/commit/08303d774132775d49d4ba767092de5d426f089d )

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

Zum Beispiel in 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);

En ff_find_hwaccel prüft das Codec- und Pixelformatpaar des Bildes und aller verfügbaren hwaccelerators.

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

Zum Beispiel, dxva2 ( https://en.wikipedia.org/wiki/DirectX_Video_Acceleration ) hat:

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

Und libavutil/pixfmt.h listet alle unterstützten HW-Decoder/Beschleuniger nach ihren Pixelformaten auf 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. 

Die eigentliche Auswahl der Pixelformate erfolgt in der Funktion, die vor ff_find_hwaccel die static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) von libavcodec/mpeg12dec.c für mpeg1/2. In früheren Versionen von ffmpeg/libavcodec prüft es avctx->xvmc_acceleration und/oder avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU oder Anrufe avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420); um in einigen Fällen die hw-Dekodierung zu ermöglichen.

In der aktuellen Version (2017) übernehmen diese und mehrere benachbarte Funktionen die Auswahl von hw coder https://github.com/FFmpeg/FFmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#L1189 .

Grundsätzlich: Hardware-Decoder und seine API (veraltet) XVMC , VDPAU , VA-API , MS DXVA oder MS Direct3D11 oder videotoolbox) sollte in Ihrem Build von ffmpeg aktiviert sein und von Ihrer Hardware unterstützt und seine Treiber/Bibliotheken (viele davon sind proprietär und sollten separat heruntergeladen werden). Manchmal -hwaccel an ffmpeg übergeben werden, oder das Plugin geladen werden. Unter Linux können Sie die Option vainfo y vdpauinfo Befehle zum Testen der Verfügbarkeit und der unterstützten Profile mit den meisten gängigen Standard-APIs für die Videodekodierung.

Die Eingabedatei (für mpeg1/2) sollte nicht in Graustufen sein, sie sollte s->chroma_format weniger von 2 (4:2:0 Chroma-Unterabtastung was für ISO/IEC MPEG und ITU-T VCEG H.26x üblich ist, aber nicht für einige MPEG-4 Part 2 und nicht für hohe 4:4:4-Varianten von 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 */
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X