跳轉到主要內容

MJPEG影片

從4.18版本開始,TouchGFX支援使用MJPEG影片。 影片可以用於創建更生動的使用者介面,或顯示簡短說明或使用者指南。

影片可透過Video小工具納入使用者介面中。 該小工具在TouchGFX Designer中可用,可以作為任意其他小工具添加到使用者介面。

Note
不支援音訊, 因此建議由影片資料移除音訊資料。

在TouchGFX Designer中使用“影片(Video)”小工具

在STM32微控制器上解碼影片需要額外的支援軟體。 在TouchGFX Generator中啟用影片支援,就可輕鬆將此項軟體納入專案中。 有了TouchGFX開發板設置(其中已啟用影片(見下面的清單)),可以輕鬆在目標上運行影片,方法是像平常一樣按下“運行目標(F6)”。

通過STM32F746Discovery使用“影片(Video)”小工具

如果你的目標程式碼中沒有影片支援,會得到編譯或連結錯誤。

MJPEG影片

MJPEG影片由打包在容器檔(.avi)中的大量JPEG圖像(幀)組成。 壓縮後的JPEG幀不能直接複製到影像緩衝區。 個別畫面必須解壓縮為RGB格式(16、24或32位元),然後才能在顯示器上顯示。

與使用RGB點陣圖相比,這種解壓縮方式的計算成本較高,並且大大降低了性能(即每秒幀數)。

JPEG壓縮的優點是大大減少了資料尺寸。

上面截圖中使用的影片像素為240 x 135。 這意味著每個16位RGB格式的幀將佔用240 x 135 x 2位元組= 64,800位元組。 該影片含有178幀(時長大約7秒) 因此,以點陣圖格式存儲的影片總大小為178 x 64,800位元組= 11,534,400位元組。 MJPEG AVI檔只有1,242,282位元組,或點陣圖大小的10.7%。

尺寸的縮減使得MJPEG影片檔對於小段影片非常有用。

尺寸的縮減會伴隨一些壓縮失真。 這些對於真實畫面通常是可以接受的,但對於高對比圖形是不可接受的。

部分STM32微控制器(如STM32F769或STM32H750)支援JPEG圖像的硬體加速解碼。 這加快了JPEG解碼,並提高了影片的可能的畫面播放速率。

JPEG幀的解碼很容易佔用16ms以上的時間(取決於MCU的速度和影片解析度)。 這意味著在大多數情況下,MJPEG影片的解碼速率低於使用者介面的正常畫面播放速率。 對於某些應用,將整體畫面播放速率降低到解碼速率是可以接受的。 對於其他應用,即使影片以20 fps的速率運行,也需要保持使用者介面60 fps的幀率。 有一個應用可作為範例:在影片旁邊有一個具有動畫效果的進度圓環。 60 fps的動畫速率讓進度圓環的效果達到最佳,即使影片只顯示20 fps幀率的新幀。

上面關於STM32F746的範例在解碼單個JPEG幀時耗費18-20 ms。

通過TouchGFX使用影片

有了TouchGFX,可以輕鬆將影片變為您使用者介面的一部分。 需要三樣東西:一個影片小工具、一個影片控制器、當然還有MJPEG影片檔。

影片小工具在使用者介面中使用,與所有其他小工具一樣。 影片控制器是構成完整TouchGFX環境(HAL、作業系統、驅動程式等)的底層軟體的一部分。

影片小工具和影片控制器

影片控制器由控制MJPEG檔解碼和緩衝區管理的軟體組成。

TouchGFX Designer自動將影片控制器包含到所有模擬器專案中。 這樣就可以在模擬器原型中輕鬆使用影片:只需添加一個影片小工具,選擇一個影片檔,然後按下 “Run Simulator(運行模擬器)”(F5).

如要在硬體上使用影片,還需目標專案(IAR、Keil、arm-gcc、CubeIDE)中有影片控制器。 這已經添加到一些TouchGFX開發板規範包(見下面的列表),但您可以通過TouchGFX Generator向任意專案添加影片支援。 請參閱Generator使用者指南

當您擁有支援影片的平臺時,可以輕鬆在TouchGFX Designer中添加和配置影片小工具。 此處詳細介紹了如何在TouchGFX Designer中使用影片小工具。

TouchGFX專案中的影片檔

當在TouchGFX Designer中包含影片檔後,它將.avi檔複製到assets/vidoes資料夾。 在程式碼生成期間,影片以.bin檔案格式被複製到generated/videos/bin,以.o檔案格式被複製到generated/videos/obj。 .o和.bin檔包含相同的資料,但是.O檔是ELF格式(這是一些編譯器和IDE的首選格式)。

在生成程式碼時執行的專案更新程式將影片檔包含在目標專案中。 這意味著影片檔被連結到可執行檔中,並且在應用程式中可用。

應用程式設計器可以添加其他影片到assets/videos資料夾。 這些也將包括在專案中。

文件generated/videos/include/videos/VideoDatabase.hpp包含與編譯到應用程式中的影片有關的符號性資訊:

const uint32_t video_SampleVideo1_240x135_bin_length = 1242282;
#ifdef SIMULATOR
extern const uint8_t* video_SampleVideo1_240x135_bin_start;
#else
extern const uint8_t video_SampleVideo1_240x135_bin_start[];
#endif

可在使用者程式碼中通過這些宣告將影片分配給影片小工具。

從使用者程式碼使用影片檔

在一些專案中,僅從TouchGFX Designer中選擇一個影片是不夠的。 例如, 您想在啟動時選擇不同的影片。 首先,必須添加影片檔到assets/videos

添加影片到assets/videos

生成程式碼(或運行make assets)時,assets/videos資料夾中的影片檔將包含在VideoDatabase.hpp中:

const uint32_t video_myVideo_bin_length = 1242282;
#ifdef SIMULATOR
extern const uint8_t* video_myVideo_bin_start;
#else
extern const uint8_t video_myVideo_bin_start[];
#endif

我們現在可以在用戶程式碼中使用這些宣告,讓影片小工具播放我們的電影:

Screen1View.cpp
#include <gui/screen1_screen/Screen1View.hpp>
#include <videos/VideoDatabase.hpp>

Screen1View::Screen1View()
{
}

void Screen1View::setupScreen()
{
Screen1ViewBase::setupScreen();

video.setVideoData(video_myVideo_bin_start, video_myVideo_bin_length);
video.setWidthHeight(240, 136);
video.play();
}

注意!影片資料現在連結到應用程式中。 可以避免這種情況,方法是不將任何影片放在assets/videos中,且手動將影片燒錄到外部flash存儲的專用區域。 然後使用flash位址傳遞位址和長度:

void Screen1View::setupScreen()
{
...
video.setVideoData((const uint8_t*)0xA0200000, 1242282);
...
}

限制

TouchGFX不支援在直向模式進行影片解碼。

支援影片功能的開發套件列表

TouchGFX Designer中的TouchGFX開發板設置包默認為這些開發套件啟用了影片功能:

  • STM32F769Discovery(硬體加速解碼)
  • STM32H750BDiscovery(硬體加速解碼)
  • STM32U5F9Discovery(硬體加速解碼)
  • STM32F746Discovery(基於軟體的解碼)

如果您正在使用其他開發套件或客製硬體,請記住在TouchGFX Generator中啟用影片支援。

創建MJPEG AVI文件

大多數影片不以MJPEG AVI檔案格式存儲,因為這不是常見的影片格式。 因此,在TouchGFX專案中使用影片檔之前,通常需要將其轉換為MJPEG格式。

可以完成轉換,例如使用FFMPEG。 還提供其他應用和線上服務。

使用FFMPEG

此處可以找到用於FFMPEG的Windows二進位檔案。

要將影片檔input.mov轉換為MJPEG格式,可使用該指令:

ffmpeg -i input.mov -s 480x272 -vcodec mjpeg -qscale 1 -an output.avi

MJPEG影片在output.avi文件中。 該檔可以複製到assets/videos中。

為了影片能保持正確的長寬比,可以以像素為單位指定寬度(這裡是480),高度“-1”(-1):

ffmpeg -i input.mov -vf scale=480:-1 -vcodec mjpeg -qscale 1 -an output.avi

可以剪切影片:使用-ss指定開始時間,使用-t或-to指定持續時間或停止時間:

ffmpeg -ss 3 -i input.mov -t 3 -s 480x272 -vcodec mjpeg -qscale 1 -an output_section.avi

或:

ffmpeg -ss 3 -i input.mov -to 5 -s 480x272 -vcodec mjpeg -qscale 1 -an output_section.avi
選項說明
-s輸出影片解析度
-qscale品質等級範圍1 - 31(從優到差)
-an去除音訊
-vf設置filter graph
-ss開始時間(以秒為單位)
-t持續時間
-to停止時間(以秒為單位)

解碼策略

如上所述,TouchGFX需要將單獨的MJPEG幀從JPEG轉換為RGB,然後才在影像緩衝區顯示。 這種解碼可以在需要時即時完成,也可以非同步完成 - 提前將下一幀解碼到影像緩衝區。

非同步解碼是由第二個任務(而不是UI任務)完成的。 這意味著在某些情況下,解碼可以與UI任務的繪製並行進行。

TouchGFX有3種策略,每種策略都有優點和缺點:

策略說明
直接解碼到影像緩衝區在需要時,將當前影片幀直接解碼到影像緩衝區
專用緩衝區將下一個影片幀解碼到影像緩衝區。 從影片緩衝區複製到影像緩衝區
雙緩衝區將下一個影片幀解碼到第二影片緩衝區。 解碼完成後,交換影片緩衝區

Designer總是為模擬器專案選擇“直接解碼到影像緩衝區”策略。 可以在Generator中設定對目標使用什麼樣的策略。

下文將詳細講解這些策略。

直接解碼到影像緩衝區

“直接解碼到影像緩衝區”策略在TouchGFX引擎的渲染階段解碼JPEG幀(參見‘渲染’章節)

直接解碼到影像緩衝區

在更新階段(參見‘更新’章節),影片小工具決定是否應該將電影提前到下一幀。 在接下來的渲染階段,JPEG幀被逐行解碼到一個“行緩衝區”。 然後對像素進行轉換以匹配幀緩存區格式,並複製到影像緩衝區。

如果影片小工具遭到其他實心小工具覆蓋,就會重繪成多個區塊(可見部分分割成矩形)。

與實心小工具重疊的影片幀於多個區塊解碼。

繪製前述各個區塊需要重複進行解壓縮。 這可能會讓此策略不適合用於按鈕等其他實心UI元素置於影片頂端的使用者介面,因為解碼時間會增加。 有一些設計決策可能限制所需的額外解壓縮工作量。 其中一種方法就是變更實心小工具,使其具備一些不透明度。 這只會在單一區塊中生效,例如整個影片幀。 小工具將與幀的內容混合。

影片幀與具不透明度的小工具在單一區塊中解碼。

另一種方法則是停用SMOC演算法;這種演算法將螢幕的繪製區域分割為區塊。 如果停用,所有小工具都會完全繪製,即使是由其他實心小工具涵蓋的區域也一樣。 這是透過useSMOCDrawing()所進行。 以下範例會為螢幕中實心小工具位於頂端的影片停用SMOC,並於螢幕完成渲染時再次啟用。

void Screen1View::setupScreen()
{
useSMOCDrawing(false);
Screen1ViewBase::setupScreen();
}

void Screen1View::tearDownScreen()
{
useSMOCDrawing(true);
Screen1ViewBase::tearDownScreen();
}

useSMOCDrawing()呼叫也能更靠近影片渲染的位置,以免也完全繪製螢幕中的其他小工具。

該解決方案的優點是只使用了很少額外記憶體。

Caution
停用SMOC繪製演算法可能意外造成其他小工具延長渲染時間,因此使用時請小心謹慎。

專用緩衝區

專用或單緩衝區解碼策略首先將JPEG幀解碼到專用RGB緩衝區,然後再從該緩衝區複製到影像緩衝區。

解碼到單獨的緩衝區

與直接策略相反,現在解碼工作在一個單獨任務(而不是通常的TouchGFX任務)中運行。 影片小工具計算一個新的電影幀是否應該在下一個使用者介面tick中顯示,並通過信號告知解碼任務開始解碼下一幀。 在解碼過程中,影片緩衝區不能被繪製到影像緩衝區(它被部分更新)。 當解碼任務正在運行時,使用者介面不得重繪影片小工具。 繪製完成後,它將繼續。 如果使用者介面不需要重繪影片,則使用者介面可以照常運行。

新影片被完全解碼後,將影片渲染到影像緩衝區的成本與繪製點陣圖的成本(低)相同。 通過該策略,在影片上放置按鈕或文字不成問題。

該策略的缺點是任務和影片緩衝區佔用記憶體。

雙緩衝區

雙緩衝區解碼策略使用兩個RGB緩衝區。 解碼在這兩個緩衝區中完成,而渲染到影像緩衝區則發生於另一個RGB緩衝區中。

解碼到兩個影片緩衝區

當一個幀被解碼後,解碼任務等待UI顯示該影片緩衝區並釋放前一個緩衝區。 一旦使用者介面改變了緩衝區,就可以開始解碼下一幀。

該策略的一個明顯缺點是記憶體使用是前一種策略的兩倍。

影片畫面播放速率和使用者介面畫面播放速率

不同的解碼策略對使用者介面畫面播放速率的影響也不同。 使用者介面畫面播放速率是每秒在影像緩衝區中產生的(不同)幀數量。

如果採用“直接解碼到影像緩衝區”策略,影片解碼速度容易影響使用者介面的有效畫面播放速率。 假設解碼一個JPEG幀需要28 ms,並且我們希望每秒顯示20幀影片(20 fps)。 這是比較實際的,因為總解碼時間是: 28 ms x 20/s = 560 ms/s。 20 fps對應於每3幀(60 fps)有一個新影片幀。 所以在每三個UI幀中,我們需要一個新的影片幀,但是由於解碼時間是渲染階段的一部分,渲染一幀需要28 ms,加上渲染使用者介面的其他部分需要(比如)2 ms。 總的幀渲染時間是30 ms,我們失去了一個tick,但我們準備為下一個tick生成一個新幀。 在下一幀中,我們沒有解碼影片,所以渲染時間低於16 ms,符合限制要求。 然後,我們可以在第四個tick中開始解碼第二個影片幀。

20 fps影片

因此,影片畫面播放速率是20 fps,使用者介面畫面播放速率是40 fps(共計60 fps)。

結果是我們不能讓UI的其他元素具有60 fps的動畫效果,因為影片解碼限制了畫面播放速率。

如果採用“雙緩衝區”策略,這種問題得到緩解。 使用者介面總是有一個可用的影片緩衝區用於最新的幀。 解碼任務可以將該緩衝區與另一個緩衝區(包含下一幀)交換(當它可用時),而渲染執行緒沒有主動繪製。 交換之後,解碼任務可以立即開始解碼下一幀:

20 fps影片

在UI幀1和UI幀2中,UI顯示的是第一個解碼的影片幀。 同時,解碼器在生成幀2。 在UI幀3中,該幀已經準備就緒並將被使用。 解碼器處於空閒狀態,可以開始解碼下一幀(圖中沒有顯示)。

因此,即使影片解碼只能每2個ticks中生成一個新幀,也可以在每幀中更新使用者介面的其他元素。

如上所述,對目標專案的影片支援是在TouchGFX Generator中配置的。 請參閱Generator使用者指南。 取得指示說明。

影片小工具在TouchGFX Designer中可用。 此處詳細介紹了如何在TouchGFX設計器中使用影片小工具。