本文主要介紹如何基于FPGA實現視頻的90度/270度無裁剪旋轉,旋轉效果示意圖如下:
為了實時對比旋轉效果,采用分屏顯示進行處理,左邊代表旋轉前的視頻在屏幕中的位置,右邊代表旋轉后的視頻在屏幕中的位置。 分屏顯示的實現方式見本專欄前面的文章詳解。
本旋轉方案不僅僅適用于國產安路FPGA,只有板卡上帶有支持AXI4總線操作DDR的IP核,均可以進行方案移植
關于FPGA實現視頻180度實時旋轉,點擊跳轉文章鏈接
關于FPGA實現視頻任意角度旋轉,點擊跳轉文章鏈接
一、前言
-
后續文章的工程代碼不在免費上傳至Github,方案是開源的,工程代碼可以私信我或者是評論區留言,有償提供(價格不貴,此文章對應的工程文件為 ¥50)。前面已經發布的文章方案和代碼均是開源的,可以直接去github下載。
-
免費內容太容易被剽竊了,付費是某種意義上的版權保護
-
付費即意味著責任,有利于提高文章質量、同時也能提高更新動力。
二、設計概述
除去DDR3控制器、FIFO等常用IP,本設計所用到的主要的IP模塊如下。
IP | 功能 | 來源 |
---|---|---|
uidbuf | 基于FDMA信號時序的緩存控制器 適合用于基于RGB時序的視頻數據或者數據流傳輸 | 米聯客 |
uiFDMA | 基于AXI總線的自定義內存控制器 簡化AXI總線的控制,完成數據的搬運 | 米聯客 |
uidbuf_w_active_rotate | 在uidbuf的基礎上進行更改 用于視頻90度/270度旋轉 | 個人開發 |
uivtc_video_rotate_90 | 在uivtc的基礎上進行更改 讀取兩路視頻,一路是旋轉之前的視頻,一路是旋轉之后的視頻 | 個人開發 |
三、系統實現方案
3.1 理論分析
在實現視頻90/270度旋轉時,我們無法像前面的文章那樣,在使用AXI4總線讀寫DDR時,把突發長度設置為一整行的像素量。
由于原始視頻在經過旋轉后,對應的像素點位置不在是連續的,因此我們不得不考慮把突發長度設置為1進行像素點的寫入/讀取。
根據現在可以找到的有關FPGA實現視頻任意角度旋轉的文章可以得知,在進行視頻旋轉時,我們可以采用正向映射/逆向映射兩種方式進行視頻旋轉的處理。
在進行視頻任意角度旋轉時(比如31度),為了保證旋轉后的視頻無空洞,需要采用逆向映射的旋轉方案進行處理(下一篇文章介紹任意角度旋轉實現方案)。
在視頻處理中,對于 90 度或 270 度的旋轉操作較為常見。由于視頻像素點在完成這類旋轉后,其排列呈現出明顯的規律性,因此針對這類旋轉的處理方式,我們可以采用正向映射的方案進行處理,把輸入進的待旋轉視頻數據依次寫入旋轉后對應的像素點位置。
3.2 數據流框圖
為了處理輸入進的60hz的待旋轉視頻,視頻像素點的數據流如上圖所示,其經歷了三進三出DDR3,最終輸出至顯示器進行顯示。
- 第一次讀寫DDR3:由于輸入進來的視頻為60幀的幀率,如果直接對視頻進行逐像素點寫入,是處理不過來的。(具體我們的板卡能實現多高的處理速率,取決于我們使用的DDR控制器IP從發起寫請求到一個像素點完全寫入需要的時間,這個需要自行計算一下)因此,第一次緩存的目的是把輸入進來的視頻數據先存進DDR3,以一個較低的幀率讀出像素數據至旋轉處理模塊。
- 第二次讀寫DDR3:把剛剛讀出的經過降幀的數據,進行90度/270度旋轉處理,然后存進DDR,并以較低的幀率讀出
- 第三次讀寫DDR3:把剛剛讀出的經過降幀的并且是旋轉后數據,再次存進DDR,然后就可以以正常的60幀讀出進行顯示。
上述處理的核心在于旋轉模塊的實現。
3.3 uidbuf_w_active_rotate模塊
此模塊采用正向映射的方法進行90度/270度旋轉,把待旋轉的數據依次寫入到像素點旋轉后對應的位置
模塊接口如下,相比于uibuf模塊,不同的部分用紅框圈出。
此方案中,使用AXI4總線讀寫DDR時,AXI4總線的數據寬度為128,像素點的數據位寬為16,因為DDR3采用的是8-bit預取,DDR3的位寬配置為16bit,所以在突發長度為1的情況下,一次可以讀出8個16bit數據(128bit),在常規情況下,一次能讀出8個像素點數據。
然而,在進行旋轉時,為了保證每一次只傳輸一個像素數據,我們把這128bit全部設置為某一個像素點的數據即可。
該模塊中核心的部分在于地址計算,詳見源代碼。
四、移植注意事項
1、本工程視頻源輸入的視頻分辨率為1280×720@60hz
2、使用串口命令發送16進制 00 視頻進行順時針90度旋轉, 01 視頻進行順時針270度旋轉,波特率為115200。
五、上板驗證
視頻旋轉效果圖如下,下圖分別為旋轉90度和270度的結果