FFmpeg為什麼遲遲不啟用vaapi解碼/編碼?
很顯然,英特爾的vaapi已經準備好了,mpv已經實現了vaapi的解碼,但FFmpeg怎麼到現在都編譯不出h264_vaapi來的?然後實現vaapi編碼是太過複雜了嗎?到現在還沒有軟體實現。
首先什麼是VAAPI
視頻圖像大小從標清,高清,升到超高清,編碼器標準從H.263,H.264升到H.265,包括目前很火的VR和AR,視頻應用對視頻處理和編解碼器的運算量要求越來越高,而GPU相比CPU更適合處理圖形圖像這樣的矩陣運算。
如何使用GPU的圖像處理能力呢,VAAPI是一個方案。視頻加速應用程序介面 (Video Acceleration API, 縮寫為VA-API) 是一套類unix平台提供視頻硬體加速的開源庫和標準。
VAAPI免費開源,以MIT許可證發布。MIT許可證源自麻省理工學院(Massachusetts Institute of Technology, MIT),又稱"X條款"(X License)或"X11條款"(X11 License) MIT內容與三條款BSD許可證(3-clause BSD license)內容頗為近似,但是賦予軟體被授權人更大的權利與更少的限制。有許多團體均採用MIT許可證。例如著名的ssh連接軟體PuTTY與X Windows System (X11)。Expat, Mono開發平台庫,Ruby on Rails, Lua 5.0 onwards等等也都採用MIT授權條款。應用層用戶可以通過VAAPI介面直接訪問加速設備驅動,使用硬體(如GPU)來加速視頻處理的應用,如視頻編碼,視頻解碼,視頻融合疊加,視頻顯示。VAAPI是Intel發起的,之初是為Intel自己的GMA(Graphics Media Accelerator)系列GPU加速。Intel也想用VAAPI替代已有的XvMC標準。但VAAPI發展到現在它不僅是針對Intel的視頻加速設備,其他廠商也能完全免費的通過VAAPI這個開放介面實現硬體圖形加速。VAAPI是偏向類unix平台的,對應windows平台的技術是 Microsoft Windows DirectX Video Acceleration(DxVA)。VAAPI可以應用在Linux, FreeBSD, Solaris和Android等類unix平台。VAAPI當初的設計偏向於硬體加速解碼器的視頻演算法如VLD, IDCT, motion compensation, deblocking。現在VAAPI不僅支持解碼,還支持主流的編碼,並且支持圖像後處理和圖像增強。隨著intel的核芯顯卡越來越強,VAAPI的功能也隨之強大。從架構圖可知VAAPI通過GPU設備驅動實現四個模塊顯存控制,編碼,解碼,圖像處理,其中編解碼器模塊可分為同一類。
顯存控制:通過用戶態的DRM訪問內核顯存。編解碼器:用戶態把編解碼器的指令傳給內核態驅動,內核態驅動再操作實體編解碼硬體。圖像處理:先調用顯示介面,通過顯示介面直接調用硬體或通過調用內核Gfx模式操作硬體。從VAAPI的架構可看出它是依賴於配套的DRM,設備驅動,內核模塊和實體硬體。以intel為例,使用VAAPI最好使用intel發布的一組套件。VAAPI編碼H264常式代碼片段如下:/*打開VA GPU設備,並初始化*/
va_dpy = va_open_display();
va_status = vaInitialize(va_dpy, major_ver, minor_ver);/*查詢硬體支持的H.264 profile等級*/
h264_profile = profile_list[i];vaQueryConfigEntrypoints(va_dpy, h264_profile, entrypoints, num_entrypoints);for (slice_entrypoint = 0; slice_entrypoint &< num_entrypoints; slice_entrypoint++) { if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice) { support_encode = 1; break; }}
/*查詢H.264 屬性介面,是否支持VBR,CBR等。是否支持多slice等*/
va_status = vaGetConfigAttributes(va_dpy, h264_profile, VAEntrypointEncSlice, attrib[0], VAConfigAttribTypeMax);CHECK_VASTATUS(va_status, "vaGetConfigAttributes");/*在指定設備上創建H.264配置*/
va_status = vaCreateConfig(va_dpy, h264_profile, VAEntrypointEncSlice, config_attrib[0], config_attrib_num, config_id);CHECK_VASTATUS(va_status, "vaCreateConfig");/* 創建源設備表面 */
/* create source surfaces */
va_status = vaCreateSurfaces(va_dpy, VA_RT_FORMAT_YUV420, frame_width_mbaligned, frame_height_mbaligned, src_surface[0], SURFACE_NUM, NULL, 0); CHECK_VASTATUS(va_status, "vaCreateSurfaces");/* 創建參考設備表面 */
/* create reference surfaces */ va_status = vaCreateSurfaces(va_dpy,
VA_RT_FORMAT_YUV420, frame_width_mbaligned, frame_height_mbaligned, ref_surface[0], SURFACE_NUM, NULL, 0 ); CHECK_VASTATUS(va_status, "vaCreateSurfaces");tmp_surfaceid = calloc(2 * SURFACE_NUM, sizeof(VASurfaceID));
memcpy(tmp_surfaceid, src_surface, SURFACE_NUM * sizeof(VASurfaceID)); memcpy(tmp_surfaceid + SURFACE_NUM, ref_surface, SURFACE_NUM * sizeof(VASurfaceID));/*創建編碼器管道,因為是異構系統用管道的方式*/
/* Create a context for this encode pipe */
va_status = vaCreateContext(va_dpy, config_id, frame_width_mbaligned, frame_height_mbaligned, VA_PROGRESSIVE, tmp_surfaceid, 2 * SURFACE_NUM, context_id); CHECK_VASTATUS(va_status, "vaCreateContext");free(tmp_surfaceid);/*為編碼申請設備上的全局指令空間 cmdbuf,控制和數據空間要分開申請,數據空間可實時申請*/
codedbuf_size = (frame_width_mbaligned * frame_height_mbaligned * 400) / (16*16);for (i = 0; i &< SURFACE_NUM; i++) {
va_status = vaCreateBuffer(va_dpy,context_id,VAEncCodedBufferType, codedbuf_size, 1, NULL, coded_buf[i]); CHECK_VASTATUS(va_status,"vaCreateBuffer");}/*裝載編碼數據到顯存*/
upload_surface_yuv(va_dpy, surface_id, srcyuv_fourcc, frame_width, frame_height, src_Y, src_U, src_V);va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
sizeof(slice_param),1,slice_param,slice_param_buf);
CHECK_VASTATUS(va_status,"vaCreateBuffer");/*準備編碼數據給目標表面*/
va_status = vaBeginPicture(va_dpy, context_id, src_surface[current_slot]);CHECK_VASTATUS(va_status,"vaBeginPicture");/*推送數據給GPU,編碼,完成後buffer自動釋放銷毀*/
va_status = vaRenderPicture(va_dpy,context_id, slice_param_buf, 1);CHECK_VASTATUS(va_status,"vaRenderPicture");/*讓設備執行*/
va_status = vaEndPicture(va_dpy,context_id);CHECK_VASTATUS(va_status,"vaEndPicture");/*釋放資源*/
vaDestroySurfaces(va_dpy,src_surface[0],SURFACE_NUM);vaDestroySurfaces(va_dpy,ref_surface[0],SURFACE_NUM);for (i = 0; i &< SURFACE_NUM; i++) vaDestroyBuffer(va_dpy,coded_buf[i]);vaDestroyContext(va_dpy,context_id);
vaDestroyConfig(va_dpy,config_id);從上面代碼片段可看出,VAAPI使用類似C/S架構,CPU側是client, GPU是server。GPU提供有限的功能,部分編碼器的細節需要在CPU側用戶自己完成,如封nal頭等,這樣意味著如果要用VAAPI開發編解碼器,需要對編解碼器內部細節非常清楚。
所以直接使用VAAPI的技術門檻很高。VAAPI是unix平台,那麼對應windows平台的GPU加速介面就是DxVA。
因為windows的霸主地位和windows天生對媒體能力親合支持(unix/liunx到目前還沒有統一的媒體平台,而windows一直有),加上windows和intel的聯合(intel有自己的核心顯卡),讓DxVA成為GPU加速最高效的工具沒有之一。DirectX Video Acceleration(DXVA)是一種在Microsoft Windows和Xbox 360平台的Microsoft API規範,能讓應用程序使用硬體GPU的運算能力。DxVA 1.0最早是在Windows 2000以及Windows 98版本開始引入的API,可以使用於VMR 7/9之上。DxVA 2.0僅適用於Windows Vista, Windows 7以及更新的版本。 這裡就不展開介紹DxVA了。VAAPI支持的設備和軟體
設備: Broadcom Crystal HD (work-in-progress):http://gitorious.org/crystalhd-video Intel Embedded Graphics Drivers (IEGD):Intel? Embedded Graphics Drivers for Intel? Architecture Intel Embedded Media and Graphics Drivers (EMGD):Intel? Embedded Media and Graphics Driver (Intel? EMGD) Intel GMA500 driver (OEM only):https://launchpad.net/~ubuntu-mobile/+archive/ppa Intel integrated G45 graphics chips:vaapi/intel-driver IMG VXD375/385 and VXE250/285 video engines:vaapi/pvr-driver VDPAU back-end for NVIDIA and VIA chipsets:vaapi/vdpau-driver VIA / S3 Graphics Accelerated Linux Driver:Welcome to S3 Graphics XvBA / ATI Graphics Backend (for proprietary driver only)vaapi/xvba-driver從上面的列表可看出,目前對VAAPI支持最好的還是intel自己。
軟體:
Clutter toolkit (through clutter-gst, thus GStreamer):http://clutter-project.org/ FFmpeg (upstream SVN tree &>= 2010/01/18 / version 0.6.x and onwards):FFmpeg Fluendo video codec pack for Intel Atom (GStreamer):http://www.fluendo.com/ Gnash flash player:http://wiki.gnashdev.org/Hardware_Video_decoding GStreamer:GitHub - 01org/gstreamer-vaapi: *WARNING* this repository is not maintained anymore. Please use https://cgit.freedesktop.org/gstreamer/gstreamer-vaapi Lightspark flash player:Lightspark MPlayer/VAAPI:GitHub - gbeauchesne/mplayer-vaapi: Original MPlayer with VA-API support MythTV (work-in-progress):VAAPI - MythTV Official Wiki ?RealPlayer for MID:https://community.helixcommunity.org/Licenses/realplayer_for_mid_faq.html Totem movie player (simply requires GStreamer VA-API plug-ins):http://projects.gnome.org/totem/VideoLAN - VLC media player:
http://www.videolan.org/ XBMC:Kodi | Open Source Home Theater Software Xine:GitHub - huceke/xine-lib-vaapi at vaapi 從上面的軟體列表可看出FFMPEG和gstreamer都支持VAAPI,特別是gstreamer已把vaapi納入他的准里,所以在類unix平台和開源GPU訪問控制方案中,VAAPI已是一支獨秀。最後
從VAAPI官網的信息可知,FFMPEG早就支持vaapi了。FFmpeg (upstream SVN tree &>= 2010/01/18 / version 0.6.x and onwards):。參考vaapiVAAPI | 01.orgffmpeg 3.1終於支持了
FFmpeg 3.1 "Laplace", a new
major release, is now available! Some of the highlights:
- DXVA2-accelerated HEVC Main10 decoding
- fieldhint filter
- loop video filter and aloop audio filter
- Bob Weaver deinterlacing filter
- firequalizer filter
- datascope filter
- bench and abench filters
- ciescope filter
- protocol blacklisting API
- MediaCodec H264 decoding
- VC-2 HQ RTP payload format (draft v1) depacketizer and packetizer
- VP9 RTP payload format (draft v2) packetizer
- AudioToolbox audio decoders
- AudioToolbox audio encoders
- coreimage filter (GPU based image filtering on OSX)
- libdcadec removed
- bitstream filter for extracting DTS core
- ADPCM IMA DAT4 decoder
- musx demuxer
- aix demuxer
- remap filter
- hash and framehash muxers
- colorspace filter
- hdcd filter
- readvitc filter
- VAAPI-accelerated format conversion and scaling
- libnpp/CUDA-accelerated format conversion and scaling
- Duck TrueMotion 2.0 Real Time decoder
- Wideband Single-bit Data (WSD) demuxer
- VAAPI-accelerated H.264/HEVC/MJPEG encoding
- DTS Express (LBR) decoder
- Generic OpenMAX IL encoder with support for Raspberry Pi
- IFF ANIM demuxer decoder
- Direct Stream Transfer (DST) decoder
- loudnorm filter
- MTAF demuxer and decoder
- MagicYUV decoder
- OpenExr improvements (tile data and B44/B44A support)
- BitJazz SheerVideo decoder
- CUDA CUVID H264/HEVC decoder
- 10-bit depth support in native utvideo decoder
- libutvideo wrapper removed
- YUY2 Lossless Codec decoder
- VideoToolbox H.264 encoder
We strongly recommend users, distributors, and system integrators to
upgrade unless they use current git master.
intel有提供一個ffvademo(https://github.com/gbeauchesne/ffvademo),可以啟用vaapi解碼。最新的ffmpeg 3.1已經啟用在ffmpeg命令里啟用了vaapi加速,真好。之前以為編碼沒放ffmpeg中,可能是為了qsv(Quick Sync Video)收費所以這樣吧。ffmpeg 2.8有包含qsv的編碼。Linux世界有一個非常不好的地方就是沒有一個標準是大家都用的,vaapi的amd支持xvba 上一次更新還是2011年,vaapi的vdpau支持也是2012年後不更新,或許未來vulkan能夠統一硬編碼也說不定。
最新ffmpeg代碼裡面有vaapi
c++ - How to use hardware acceleration with ffmpeg 不負責任的給一個鏈接,看看是否有幫助
推薦閱讀: