2011-05-12 242 views
12

如何使用ffmpeg通過硬件加速解碼文件?使用ffmpeg hwaccel from C++

我寫了一個使用ffmpeg的工作視頻播放器。 我使用"av_hwaccel_next"檢查了支持,發現mpeg2_dxva

但是,當我加載mpeg2文件(像往常一樣)時,我沒有得到任何硬件加速。 AVCodecContext->hwaccelAVCodecContext->hwaccelcontext都是空的。

爲了啓用hw加速,我需要在某處傳遞一些標誌嗎?

我一直無法找到任何有關這方面的信息,任何人都知道一個好的來源?

回答

15

開始閱讀的ffmpeg文檔:https://trac.ffmpeg.org/wiki/HWAccelIntro和更好的答案How to use hardware acceleration with 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檢查編解碼器和像素格式控制一對圖像和所有可用的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; 
} 

例如,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. 

的像素格式實際選擇是在函數ff_find_hwaccel之前調用,static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx)libavcodec/mpeg12dec.c爲mpeg1/2。在早期版本的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(過時XVMCVDPAUVA API,MS DXVA或MS Direct3D11,或videotoolbox)應該在你的ffmpeg的構建和supported by your hardware及其驅動器/庫(許多是專有的,應該是被啓用單獨下載)。有時-hwaccel選項應給予ffmpeg或插件加載。在linux下你可以使用vainfovdpauinfo命令用最流行的標準視頻解碼硬件的API來測試可用性和支持的配置文件。輸入文件(對於mpeg1/2)應該不是灰度,它應該少於2(4:2:0)Chroma subsampling,這對於ISO/IEC MPEG和ITU-T VCEG H.26x通常是這樣;但是對於mpeg1/2,輸入文件應該不是灰度不適用於某些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 */ 
    } 
} 
+0

那麼我是否需要手動覆蓋avctx的pix_fmt到PIX_FMT_DXVA2_VLD?當我查看ffmpeg代碼時,我只能看到這個值被讀取,從來沒有設置。 – ronag 2011-05-13 07:34:24

+0

沒有文件將是PIX_FMT_DXVA2_VLD格式。看來,在FFmpeg的hwaccel的不存在的文件...... – Maypeur 2017-02-27 16:40:29

+0

@Maypeur,文檔現在是官方:https://trac.ffmpeg.org/wiki/HWAccelIntro,還要檢查https://wiki.archlinux.org/index.php/Hardware_video_acceleration。你提的問題都需要任何細節(的ffmpeg版本,操作系統Linux/Windows的/其他;你有什麼硬件解碼器,並安裝它,什麼是它的API,你有什麼文件,你是怎麼開始的ffmpeg,並硬件解碼時開始工作來自命令行的'ffmpeg')並且無法應答。但我原來的答案不是很正確([「不解決任何問題」)(http://stackoverflow.com/questions/23289157/#comment35652265_23289157)),所以我更新了一下。 – osgx 2017-02-27 20:39:38