跳轉到主要內容

MJPEG影片

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

Video is included in the user interface through the Video Widget. 該小工具在TouchGFX Designer中可用,可以作為任意其他小工具添加到使用者介面。

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

在STM32微控制器上解碼影片需要額外的支援軟體。 This software is easily included in the project by enabling video support in the TouchGFX Generator. 有了TouchGFX開發板設置(其中已啟用影片(見下面的清單)),可以輕鬆在目標上運行影片,方法是像平常一樣按下“運行目標(F6)”。

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

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

MJPEG影片

MJPEG影片由打包在容器檔(.avi)中的大量JPEG圖像(幀)組成。 壓縮後的JPEG幀不能直接複製到影像緩衝區。 The individual frames must be decompressed into RGB format (16, 24 or 32 bit) before they can be shown on the display.

與使用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向任意專案添加影片支援。 See the Generator User Guide.

當您擁有支援影片的平臺時,可以輕鬆在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);
...
}

Limitations

TouchGFX does not support video decoding in portrait mode.

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

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

  • STM32F769Discovery(硬體加速解碼)
  • STM32H750BDiscovery(硬體加速解碼)
  • 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總是為模擬器專案選擇“直接解碼到影像緩衝區”策略。 The strategy used on target is configurable in the Generator.

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

直接解碼到影像緩衝區

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

直接解碼到影像緩衝區

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

如果影片小工具被其他小工具覆蓋,它會被重繪成多個塊(可見部分被分割成矩形)。 繪製每一個這樣的塊需要反復進行解壓縮工作。 這使得該策略不適合使用者介面,因為隨著解碼時間的增加,那裡的其他UI元素(如按鈕)會被置於影片的頂部。

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

專用緩衝區

專用或單緩衝區解碼策略首先將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中配置的。 See the Generator User Guide. for instructions.

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