2011-05-12 13 views
12

Bir dosyayı ffmpeg ile donanım hızlandırma ile nasıl çözebilirim?ffmpeg hwaccel kullanarak C++

Ffmpeg kullanan bir çalışan video oynatıcı yazdım. "av_hwaccel_next" kullanarak destek için kontrol ettim ve mpeg2_dxva bulundu. Ancak, bir mpeg2 dosyası yüklediğimde (normalde olduğu gibi) herhangi bir donanım hızlandırması elde edemiyorum. AVCodecContext->hwaccel ve AVCodecContext->hwaccelcontext her ikisi de boş.

Hızlanma hızını sağlamak için bir yere bayrak koymalı mıyım?

Bu konuda herhangi bir bilgiyi bulamadım, herkes iyi bir kaynak biliyor mu?

cevap

15
Başlangıç ​​okuma ffmpeg belgelerinden

: https://trac.ffmpeg.org/wiki/HWAccelIntro ve daha iyi cevap How to use hardware acceleration with ffmpeg (ve linux onay sayfası https://wiki.archlinux.org/index.php/Hardware_video_acceleration için)

aracı FFmpeg kullanarak, HW-destekli çözme bir olanak -hwaccel seçeneği aracılığıyla kullanarak etkindir özel kod çözücü. Her bir kod çözücünün belirli sınırlamaları olabilir (örneğin bir H.264 kod çözücüsü sadece temel profili destekleyebilir). HW destekli kodlama, belirli bir kodlayıcının kullanımıyla (örneğin h264_nvenc) etkinleştirilir. HW destekli işlemeyi filtrelemek yalnızca birkaç filtrede desteklenir .. Bazı donanım hızlandırma standartları API'sı, bazıları FFmpeg tarafından bir ölçüde desteklenmektedir.

hwaccel aktivasyonu 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 kontrol codec ve PixelFormat içinde (2013 https://github.com/FFmpeg/FFmpeg/commit/08303d774132775d49d4ba767092de5d426f089d sonra yeniden biçimlendirilmiş bit) Örneğin

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

, gibi bir kod ile kontrol edilmiştir görüntü ve mevcut tüm hwaccelerators çifti. Örneğin

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) sahiptir:

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

Ve libavutil/pixfmt.h listeleri tüm desteklenen hw kod çözücüleri/hızlandırıcılar onların piksel biçimlerinde tarafından piksel biçimleri 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. 

Gerçek seçim olduğunu işlevinde, ff_find_hwaccel, mpeg1/2 için libavcodec/mpeg12dec.c'un static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) adı verilir. Ffmpeg/libavcodec'in önceki sürümlerinde, bazı durumlarda hw kodlamasını etkinleştirmek için avctx->xvmc_acceleration ve/veya avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU veya avctx->get_format(avctx,ff_hwaccel_pixfmt_list_420); çağrılarını denetler.

Son sürümde (2017), ve yakınlardaki birkaç işlev, hw kodlayıcı https://github.com/FFmpeg/FFmpeg/blob/aff8cf18cb0b1fa4f2e3d163c3da2f25aa6d1906/libavcodec/mpeg12dec.c#L1189'un seçimini yapar.

Temelde: donanım kod çözücü ve API (eskimiş XVMC, VDPAU, VA API MS DXVA veya MS Direct3D11 veya VideoToolbox) ekleyin Ffmpeg üzerindeki yapım ve supported by your hardware ve sürücü/kütüphaneler (birçok kişiye özeldir olmalıdır etkinleştirilmelidir ayrı olarak indirilir). Bazen -hwaccel seçeneği ffmpeg'e veya eklentiye yüklenmiş olmalıdır. Linux'ta en popüler standart video hw kod çözme API'ları ile kullanılabilirliği ve desteklenen profilleri test etmek için vainfo ve vdpauinfo komutlarını kullanabilirsiniz. 2: (MPEG1/2) olup Gri Tonlama olmalıdır

çıktı dosyası, bu 2 (4 s->chroma_format daha az olması gerekir, ISO/IEC MPEG ve ITU-T VCEG H.26x için alışılmış 0 Chroma subsampling, fakat Bazı MPEG-4 Part 2 için değil, yüksek 4: 4: 4 H.264/MPEG-4 AVC varyantları için değil.

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 */ 
    } 
} 
+0

yüzden elle PIX_FMT_DXVA2_VLD için avctx ait pix_fmt geçersiz kılmak gerekir? Ffmpeg kodunu incelediğimde sadece okunan bu değeri görüyorum, asla ayarlamam. – ronag

+0

Hiçbir dosya PIX_FMT_DXVA2_VLD biçiminde olmayacak. FFmpeg hwaccel ... – Maypeur

+0

@Maypeur, Belgelendirme şu anda resmi olmayan bir belge var gibi görünüyor: https://trac.ffmpeg.org/wiki/HWAccelIntro, ayrıca https://wiki.archlinux.org/index.php adresini de kontrol edin/Hardware_video_acceleration. Sorunuz, Diğer OS Linux/Windows/hayır gerekli ayrıntılar (Ffmpeg sürümü var; başlarken sizin hw dekoder ve yüklü olduğu ne, ne onun API, dosya nedir, sen ffmpeg başladınız nasıl hw kod çözme işleri yok 'ffmpeg' komut satırından) ve cevaplanamaz. Ama orijinal cevabım çok doğru değildi (["bir şeyi çözmüyor"] (http://stackoverflow.com/questions/23289157/#comment35652265_23289157)), bu yüzden biraz güncelledim. – osgx