ビデオ・デコーディング
このセクションでは、ビデオ・デコーディング機能を備えたTouchGFX HALを生成するためのTouchGFX Generatorの設定方法について説明します。
このシナリオを読む前に、TouchGFXでのMJPEGビデオの使用に関するドキュメントおよびビデオ・ウィジェット自体に関するドキュメントに目を通してください。
次のシナリオでは、ソフトウェア(LibJPEG)またはハードウェア(JPEG)のいずれかを使用してTouchGFX HALでビデオ・デコーディングをサポートできるようにする方法について詳しく説明します。
特定のプロジェクト向けにマイクロコントローラを設定する前に、必ずこの記事のすべてのセクションをお読みください。
通常、LibJPEG設定とJPEG設定は、STM32CubeMXの[Middleware]および[Multimedia]カテゴリに含まれています。
Tip
- Several of the TouchGFX Board Setups (TBSs) in TouchGFX Designer include support for MJPEG video decoding.
- Use the STM32CubeMX configurations found in these example projects as inspiration to enable MJPEG video decoding on your specific MCU.
- An example of software decoding can be found in the TBS for STM32H735G-DK, while hardware decoding is used in the TBS for STM32U5G9J-DK2.
RTOSのサポート
The Generator User Guide mentions that Single- and Double buffer video decoding strategies require a CMSIS compliant RTOS, such as FreeRTOS. TouchGFX GeneratorはvideoTaskFunc()
エントリ・ポイント関数を生成します。この関数はビデオ・デコーディング・タスクと関連付ける必要があります。 STM32CubeMXでは、FreeRTOSミドルウェア設定の[Tasks and queues]タブでタスクとエントリ・ポイント関数を定義することにより、この設定を生成できます。
ビデオ・タスク・スタック・サイズ(CMSIS V2の場合はワード数で定義)とRTOSヒープ・サイズは2つの重要な要素です。
For software decoding, the stack size must be carefully set because LibJPEG uses dynamic memory allocation. This means that the FreeRTOS heap should be large enough to accommodate your general application + 0xA000
(~41kB). For hardware decoding, the stack size can be substantially lower because there is no software stack that dynamically allocates memory.
上記の設定に基づいて、STM32CubeMXはビデオ・タスク用に次のコードを生成します。
main.c
/* Definitions for VideoTask */
osThreadId_t VideoTaskHandle;
const osThreadAttr_t VideoTask_attributes = {
.name = "VideoTask",
.stack_size = 1000 * 4,
.priority = (osPriority_t) osPriorityLow,
};
...
void main()
{
...
/* creation of VideoTask */
VideoTaskHandle = osThreadNew(videoTaskFunc, NULL, &VideoTask_attributes);
...
}
FreeRTOSConfig.h
#define configTOTAL_HEAP_SIZE ((size_t)75000)
ソフトウェア・デコーディング
ソフトウェア・デコーディング・ソリューションでは、Generatorユーザガイドで定められているように、LibJPEGミドルウェアをSTM32CubeMXから有効化する必要があります。 ソフトウェア・デコーディングの設定は、すべてのLibJPEG対応マイクロコントローラ(STM32F4、STM32F7、STM32H7)で同じです。
TouchGFX Software Decoderでは、LibJPEGでデコードされるデータのピクセル順序をBGRにする必要があります。 この設定がRGBのままの場合は、R色成分とB色成分がアプリケーション内でスワップされます。
さらに、各ピクセルのサイズは、16ビットまたは24ビットのビデオRGBバッファを使用する場合は3バイト、32ビットのビデオRGBバッファを使用する場合は4バイトにする必要があります。
Caution
- The RGB_ORDERING setting must be configured as BGR, and the pixel size must be set according to which video RGB buffer format is used.
- If your application uses Direct to Framebuffer strategy in a ARGB8888 (32-bit) application the pixel size must be set to 4.
ビデオ・データ
TouchGFX links the video data to the ExtFlashSection
, which needs to be defined in the linker script. If ExtFlashSection
is placed in non-memory-mapped flash, the data must be read from the flash memory using a data reader and handed to the decoder.
For projects with video data in non-memory-mapped memory, please refer to the FileReader
section later in this article in this article.
ハードウェア・デコーディング
The Generator User Guide mentions that the JPEG IP must be enabled in STM32CubeMX to enable hardware decoding.
JPEG設定にあるRGB_FORMAT
の設定は、TouchGFXフレームバッファのピクセル・フォーマットに従う必要があります(下の例ではJPEG_RGB565
)。
When using hardware decoding, a DMA is used to transfer data to (memory-to-peripheral) and from (peripheral-to-memory) the JPEG IP. Which DMA to use and how to configure it differs between MCU families.
Tip
- STM32U5G9J-DK2: JPEG + GPDMA
- STM32H750B-DK: JPEG + MDMA
- STM32H7S78-DK: JPEG + HPDMA
STM32H750 example
Here is an example of how to set up the DMA on STM32H750 for JPEG decoding. For the STM32H750, the JPEG peripheral must be configured to use the MDMA peripheral instead of the regular DMA peripherals. Add an MDMA configuration for both the input and output FIFO threshold signals, as shown in the image below. The configuration is identical for both the input and output buffers.
FileReader
インタフェース
MJPEGビデオを非メモリ・マップド・メモリに格納すると、開発者は、デコーディング用にデータを設定済みのデコーダ(ソフトウェア / ハードウェア)に渡すためにTouchGFXビデオ・コントローラで使用できるtouchgfx::VideoDataReader
の実装を指定できます。 以下に、ビデオ・データを1つのバッファから別のバッファにコピーするインタフェースなどの簡単な例を示します。
VideoView.cpp
class MyReader : public touchgfx::VideoDataReader
{
public:
MyReader() : position(0) { }
virtual uint32_t getDataLength() { return video_len; }
virtual void seek(uint32_t pos) { position = pos; }
virtual bool readData(void* dst, uint32_t bytes)
{
memcpy(dst, &video_data[position], bytes);
position += bytes;
return true;
}
private:
uint32_t position;
} myReader;
Video
ウィジェットでマップド・メモリ内のビデオの開始位置をポイントするかわりに、開発者はデータ・リーダを使用するようにウィジェットを設定できます。
VideoView.cpp
video.setVideoData(myReader);
TBSを移行してビデオ・デコーディングに対応
ビデオ・デコーディングをサポートするマイクロコントローラでTouchGFX Board Setup(TBS)から作成したプロジェクトを、ビデオ・デコーディングがサポートされる前のTouchGFX Designerのバージョンから移行し、そのプロジェクトでTouchGFX Designerの[Run Target]を使用できるようにしたい場合は、GCC Makefileにいくつかの変更を手動で加える必要があります。
必要な変更の概要およびその変更が必要な理由については、後続のセクションで説明します。 常に適用する必要がある一般的な変更と、開発者のアプリケーションの使用内容に応じて、LibJPEG(ソフトウェア・デコーディング)やJPEG(ハードウェア・デコーディング)に固有の変更があります。 変更により、以前のTBSから作成された既存のGCC Makefileが拡張されます。
Makefileの更新以外にも、上記のシナリオで説明したように、STM32CubeMXでビデオ・デコーディングを設定する必要があります。
一般的な変更
LIBJPEGパスをプロジェクトに定義します。
# LibJPEG path
libjpeg_path := $(cubemx_middlewares_path)/Third_Party/LibJPEG
次に、ビデオ・アセット入力パスを定義します。
asset_texts_input := TouchGFX/assets/texts
asset_videos_input := TouchGFX/assets/videos
ビデオ・アセット出力パスも、既存のアセット出力パスの下に定義する必要があります。
asset_images_output := $(asset_root_path)/images
asset_fonts_output := $(asset_root_path)/fonts
asset_texts_output := $(asset_root_path)/texts
asset_videos_output := $(asset_root_path)/videos
ビデオ出力アセットをコンポーネント・リストに追加します。
all_components := $(components) \
$(asset_fonts_output) \
$(asset_images_output) \
$(asset_texts_output)
$(asset_texts_output) \
$(asset_videos_output)
ビデオ・オブジェクト・ファイルを定義します。 ビデオ・オブジェクト・ファイルは既存のオブジェクトから区別します。
c_source_files := $(call find, $(source_paths),*.c) $(os_source_files) $(board_c_files)
source_files += $(board_cpp_files)
video_object_files := $(call find, $(asset_videos_output),*.o)
ビデオ・コンバータ・スクリプトへのパスを定義します。
textconvert_script_path := $(touchgfx_path)/framework/tools/textconvert
textconvert_executable := $(call find, $(textconvert_script_path), *.rb)
videoconvert_script_path := $(touchgfx_path)/framework/tools/videoconvert
オプションでecho
を追加して、すべてのビデオ・オブジェクト・ファイルを表示できます。 ビデオ・オブジェクト・ファイルをリンク設定ステージに追加します。 この行には他のオブジェクト・ファイルとともに追加される$(video_object_files)を指定します。
$(binary_output_path)/$(target_executable): $(object_files) $(object_asm_files)
@echo Video Objects: $(video_object_files)
@echo Linking $(@)
@mkdir -p $(@D)
@mkdir -p $(object_output_path)
@$(file >$(build_root_path)/objects.tmp) $(foreach F,$(object_files) $(video_object_files),$(file >>$(build_root_path)/objects.tmp,$F))
ビデオ・ルールを既存のassetsと.PHONYに追加します。
_assets_: BitmapDatabase TextKeysAndLanguages Videos
.PHONY: BitmapDatabase TextKeysAndLanguages Videos
ビデオ・ルールをビデオ変換とともに追加します。
Videos:
@ruby $(videoconvert_script_path)/videoconvert.rb $(asset_videos_input) $(asset_videos_output)
最後に、クリーンなルールを更新して、ビデオ関連の出力も除去します。
_clean_:
@echo Cleaning: $(board_name)
@rm -rf $(build_root_path)
# Do not remove gui_generated
@rm -rf $(asset_images_output)
@rm -rf $(asset_fonts_output)
@rm -rf $(asset_texts_output)
@rm -rf $(asset_videos_output)
# Create directory to avoid error if it does not exist
@mkdir -p $(asset_root_path)
# Remove assets folder if it is empty (i.e. no gui_generated folder)
@rmdir --ignore-fail-on-non-empty $(asset_root_path)
# Clean bootloader project
@$(MAKE) -r -f ExtMem_Boot/gcc/Makefile -s $(MFLAGS) clean
ソフトウェアの変更
すべてのLIBJPEGパスをインクルード・パスに追加します。
include_paths := $(library_includes) \
$(foreach comp, $(all_components), $(comp)/include) \
$(foreach comp, $(cubemx_components), $(comp)/Inc) \
$(foreach comp, $(touchgfx_generator_components), $(comp)/generated) \
$(framework_includes) \
$(cubemx_middlewares_path) \
$(touchgfx_middlewares_path) \
$(touchgfx_generator_components) \
LIBJPEG/Target \
$(libjpeg_path)/include \
LIBJPEG/App
LIBJPEGソース・パスを定義します。
c_source_files := $(call find, $(source_paths),*.c) $(os_source_files) $(board_c_files)
source_files += $(board_cpp_files)
libjpeg_source_path = Middlewares/Third_Party/LibJPEG/source
次に、すべてのLIBJPEGソース・ファイルをboard_c_filesに追加します。
oard_c_files := \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_bus.c \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_qspi.c \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_sdram.c \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_ts.c \
$(Drivers_path)/BSP/Components/ft5336/ft5336.c \
$(Drivers_path)/BSP/Components/ft5336/ft5336_reg.c \
$(Drivers_path)/BSP/Components/mt25tl01g/mt25tl01g.c \
$(Drivers_path)/BSP/Components/mt48lc4m32b2/mt48lc4m32b2.c \
$(libjpeg_source_path)/jaricom.c \
$(libjpeg_source_path)/jcomapi.c \
$(libjpeg_source_path)/jdapimin.c \
$(libjpeg_source_path)/jdapistd.c \
$(libjpeg_source_path)/jdarith.c \
$(libjpeg_source_path)/jdatasrc.c \
$(libjpeg_source_path)/jdcoefct.c \
$(libjpeg_source_path)/jdcolor.c \
$(libjpeg_source_path)/jddctmgr.c \
$(libjpeg_source_path)/jdhuff.c \
$(libjpeg_source_path)/jdinput.c \
$(libjpeg_source_path)/jdmainct.c \
$(libjpeg_source_path)/jdmarker.c \
$(libjpeg_source_path)/jdmaster.c \
$(libjpeg_source_path)/jdmerge.c \
$(libjpeg_source_path)/jdpostct.c \
$(libjpeg_source_path)/jdsample.c \
$(libjpeg_source_path)/jdtrans.c \
$(libjpeg_source_path)/jerror.c \
$(libjpeg_source_path)/jidctflt.c \
$(libjpeg_source_path)/jidctfst.c \
$(libjpeg_source_path)/jidctint.c \
$(libjpeg_source_path)/jmemmgr.c \
$(libjpeg_source_path)/jmemnobs.c \
$(libjpeg_source_path)/jquant1.c \
$(libjpeg_source_path)/jquant2.c \
$(libjpeg_source_path)/jutils.c \
LIBJPEG/App/libjpeg.c
さらに、その他のミドルウェア・ソース・ファイルと同じ方法で、LIBJPEGソース・ファイルを既存のオブジェクト・ファイルに追加します。
# Start converting paths
object_files := $(object_files:$(touchgfx_path)/%.cpp=$(object_output_path)/touchgfx/%.o)
object_files := $(object_files:%.cpp=$(object_output_path)/%.o)
object_files := $(object_files:$(touchgfx_middlewares_path)/%.c=$(object_output_path)/$(touchgfx_middlewares_path)/%.o)
object_files := $(object_files:$(cubemx_middlewares_path)/%.c=$(object_output_path)/$(cubemx_middlewares_path)/%.o)
object_files := $(object_files:$(libjpeg_source_path)/%.c=$(object_output_path)/$(libjpeg_source_path)/%.o)
object_files := $(object_files:$(Drivers_path)/%.c=$(object_output_path)/Drivers/%.o)
object_files := $(object_files:%.c=$(object_output_path)/%.o)
ハードウェアの変更
すべてのJPEGパスをインクルード・パスに追加します。
include_paths := $(library_includes) \
$(foreach comp, $(all_components), $(comp)/include) \
$(foreach comp, $(cubemx_components), $(comp)/Inc) \
$(foreach comp, $(touchgfx_generator_components), $(comp)/generated) \
$(framework_includes) \
$(cubemx_middlewares_path) \
$(touchgfx_middlewares_path) \
$(touchgfx_generator_components) \
Utilities/JPEG
次に、すべてのJPEGソース・ファイルをboard_c_filesに追加します。
board_c_files := \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_bus.c \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_qspi.c \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_sdram.c \
$(Drivers_path)/BSP/STM32H750B-DK/stm32h750b_discovery_ts.c \
$(Drivers_path)/BSP/Components/ft5336/ft5336.c \
$(Drivers_path)/BSP/Components/ft5336/ft5336_reg.c \
$(Drivers_path)/BSP/Components/mt25tl01g/mt25tl01g.c \
$(Drivers_path)/BSP/Components/mt48lc4m32b2/mt48lc4m32b2.c \
Utilities/JPEG/jpeg_utils.c
外部メモリへのビデオ・バッファの配置
When developers create new projects with STM32CubeMX, the linker scripts associated with the generated projects do not contain default regions used by TouchGFX. Because of this, 'ExtFlashSection' where the video is stored is placed in internal flash by default. It will often be required to place 'ExtFlashSection' in external flash memory to avoid running out of internal flash memory.
Tip
- STM32F746-DISCO
- STM32H735G-DK
- STM32H750-DK
- STM32U5G9J-DK2
If the video strategy selected is not direct to framebuffer, an RGB buffer dedicated to JPEG decoding is generated by TouchGFX Generator when video is enabled. この定義には、バッファを配置するセクションをリンカに通知するロケーション・プラグマが付随しています。 リンカがこのメモリ領域をリンカ・スクリプトで検出できない場合は、バッファは内部メモリに配置されます。
LOCATION_PRAGMA_NOLOAD("Video_RGB_Buffer")
uint32_t videoRGBBuffer[57600] LOCATION_ATTRIBUTE_NOLOAD("Video_RGB_Buffer");
The following compiler-specific subsections describe an example of the modifications that developers can make to achieve placing the buffer in SDRAM on STM32F746G-DISCO. Video_RGB_Buffer
は、ビデオ・デコーディングに使用されるバッファを表しています。 サンプルのリンカ・スクリプトでは、TouchGFXフレームバッファ用にSDRAMのいくらかのスペース(0xC0000000
から開始)を確保しています。
- EWARM
- STM32CubeIDE
- MDK-ARM
Further reading
以下のすべての例では、STM32F746G-DISCOボードのSDRAMの開始アドレス(0xC0000000
->0xC00FF000
)からスペースを確保し、リンカがフレームバッファのデータを上書きするリスクなしに、アプリケーションがアドレス(0xC0000000
など)を使用してフレームバッファを参照できます。 各例で、リンカは定義されているSDRAM領域にVideo_RGB_Buffer
を配置できます。
Tip
EWARM(IAR)
stm32f746xx_flash.icf
define symbol __ICFEDIT_region_SDRAM_start__ = 0xC00FF000;
define symbol __ICFEDIT_region_SDRAM_end__ = 0xC0700FFF;
define region SDRAM_region = mem:[from __ICFEDIT_region_SDRAM_start__ to __ICFEDIT_region_SDRAM_end__];
place in SDRAM_region { first section Video_RGB_Buffer };
リンク設定すると、 EWARM\STM32F746G_DISCO\List\STM32F746G_DISCO.map
には、Video_RGB_Buffer
に関する次の配置情報が含まれます。
STM32F746G_DISCO.map
Video_RGB_Buffer zero 0xc00f'f000 0x3'8400 TouchGFXGeneratedHAL.o [2]
- 0xc013'7400 0x3'8400
STM32CubeIDE
STM32F746NGHX_FLASH.ld
MEMORY
{
...
SDRAM (xrw) : ORIGIN = 0xC00FF000, LENGTH = 8M
}
BufferSection (NOLOAD) :
{
*(Video_RGB_Buffer Video_RGB_Buffer.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >SDRAM
コンパイルすると、STM32CubeIDE\Debug\STM32F746G_DISCO.map
には、Video_RGB_Buffer
に関する次の配置情報が含まれます。
STM32F746G_DISCO.map
BufferSection 0x00000000c00ff000 0x1c200
*(Video_RGB_Buffer Video_RGB_Buffer.*)
Video_RGB_Buffer
0x00000000c00ff000 0x1c200 Application/User/TouchGFX/target/generated/TouchGFXGeneratedHAL.o
0x00000000c00ff000 videoRGBBuffer
MDK-ARM(Keil)
STM32F746G_DISCO.sct
LR_IROM1 0x08000000 0x00200000 { ; load region size_region
ER_IROM1 0x08000000 0x00200000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00050000 { ; RW data
.ANY (+RW +ZI)
}
RW_SDRAM 0xC00FF000 UNINIT 0xC0700FFF {
*.o (Video_RGB_Buffer)
}
}
ビデオバッファを保持するセクションにUNINIT
属性を必ず含めてください。 これにより、初期化されていないデータとしてメモリ領域が確実に残されます。 リンク設定すると、 MDK-ARM\STM32F746G_DISCO\STM32F746G_DISCO.map
には、Video_RGB_Buffer
に関する次の配置情報が含まれます。
STM32F746G_DISCO.map
Video_RGB_Buffer 0xc00ff000 Section 115200 touchgfxgeneratedhal.o(Video_RGB_Buffer)