我正在開發一個特殊的視頻播放器,它在每個解碼幀上應用「濾鏡」。我目前的目標是縮放解碼的幀(當然除了內存限制外沒有任何限制)。縮放IDirect3DSurface9
解碼部分使用ffmpeg(av_read_frame,avcodec_send_packet,avcodec_receive_frame)完成。 Media Foundation的EVR被用作視頻渲染。 更準確地說,我檢索一個「樣本」(它只是一個圍繞d3d平面離屏表面的包裝),ffmpeg使用這個緩衝區來存儲解碼後的幀,並且將這個「樣本」給予緩存它的呈現器,然後呈現它在屏幕上需要時(從採樣時間戳,播放速率和系統時鐘顯示時間)。
我從可用曲面池(通過IMFVideoSampleAllocator)檢索曲面(format = X8R8G8B8,type = D3DRTYPE_SURFACE,usage = 0,pool = D3DPOOL_DEFAULT,multisample = DDMULTISAMPLE_NONE)。使用RGB32數據是一項要求,如果需要,解碼幀將被轉換。
關於縮放功能/縮放濾鏡,我首先在SWS_FAST_BILINEAR中使用了libswscale(sws_scale函數),但是從1920x800到1920x400(用於測試目的的固定值)將框架調整大約需要80ms。然後我嘗試使用簡單的雙線性算法來縮放自己,但它更糟糕,並且需要很長時間才能完成。
我已經做了一個最小的測試用例,它加載一個BMP文件,對它進行縮放並將縮放數據寫入另一個BMP。令人驚訝的是,相同的代碼需要〜15 ms(libswcale)或〜30 ms(天真的雙線性)。
然後我修改我的視頻播放器,使用av_image_alloc和av_image_copy_to_buffer。分配不需要時間,複製需要一整秒,縮放需要5毫秒。整個部分實時縮放太慢,但它表明內存「起源」(malloc'ed或d3d表面)有很大差異。
數據對齊可能是緩慢的原因,但我的測試用例在內存中使用相同的模式(stride = width * 4,自下而上),速度更快。我打印輸入和輸出緩衝區%16,它是0,所以它對我來說似乎安全。
我也嘗試過使用StretchRect方法,但它在離屏表面之間不起作用。
有什麼想法? 注意:我計劃創建曲面並自己呈現它們,所以渲染器部件對我來說是一個弱依賴項。 所以,如果你有一個普通的D3D樣本作爲參考,我會接受它。
我認爲您可以使用DXVA2/DXVA-HD進行縮放。 – VuVirt