最近偶然看到B站bad apple的视频, 是基于stm32单片机的,心血来潮自己也来弄了一个车模小视频,哈哈。。。
stm32f103_lvgl_sd_video_bin
?
和bad apple的播放原理一样,视频其实就是一张张小图片,保存为.bin二进制文件格式,放在SDcard里面,通过stm单片机读取SD的bin文件,再显示在TFT上面。
第一步,截取视频图片。
截取视频图片的方法很多,这里选择通过KMPlayer播放截取一段视频。
右键视频,打开提取窗口.
?
?因为用的是160*80的16位TFT屏,想要视频播放速度正常,我选择Every Frame,虽然图片的数量增加了很多,但是保存在SD里,谁在乎大小(哈)。 Prefix是图片名+4位数字。点击Start就可以截取大小160*80的bmp图片了。
第二步,合成bin文件。
先把每张小图片转换成单独的bin文件。 这里使用牛人写的小软件Lvgl_image_convert_tool-master。 是的,没错,我的stm32程序使用了lvgl, 通过lvgl来播放我们的图片。
通过上面的设置转换就可以。 输出格式这里选择了 Bin_565_swap. 因为TFT是16bit, RGB565格式,lvgl的SPI是每次发送8bit, 所以定义了swap,分2次发。?
如何把这些小bin文件合并成一个文件呢? 使用windows cmd命令就可以。win+r 打开run窗口,输入cmd. 假设我bin文件放在F盘batch文件夹下面,输入命令
pushd f:\batch 切换到batch文件夹, 再输入 copy /b *.bin f:\backtest.bin 就可以生成最后合并的文件。(so easy)
第三步,同过lvgl显示合并后的bin文件。
因为只是要连续播放图片数据,所以这里我把每张图片当做一个背景图片来显示(应该还有其他方法,懒得想,嘿)。 移植好lvgl + fatfs后,在需要显示的插入下面代码就OK了。 lvgl版本用的是6.0.0.
uint32_t offset = 0 ;
uint32_t br;
lv_fs_file_t lv_file;
lv_fs_res_t lv_res;
lv_res = lv_fs_open( &lv_file, "S:/backtest.bin", LV_FS_MODE_RD );
if ( lv_res != LV_FS_RES_OK ) {
printf( "LVGL FS open error. (%d)\r\n", lv_res );
} else
printf( "LVGL FS open Ok\r\n" );
lv_res = lv_fs_size(&lv_file,&file_size);
if ( lv_res != LV_FS_RES_OK ) {
printf( "lv_fs_size error. (%d)\r\n", lv_res );
} else
printf( "lv_fs_size Ok\r\n" );
lv_obj_t * imgBg = lv_img_create(lv_scr_act(), NULL);
lv_img_dsc_t testimg = {
.header.always_zero = 0,
.header.w = 160,
.header.h = 80,
.data_size = 12800 * 3,
.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA,
};
offset += 4; //从offset=4 读取图片数据,为什么? 因为转换后的bin图片文件加了4个字节的数据
lv_fs_seek(&lv_file, offset);
//计算bin文件里一共包含多少张图片,然后不断的给tft进行显示
for(int i = 0 ; i < file_size / 38404 ; i++)
{
//读取一张图片,图片数据的大小是38400,将读取出来的图片存放到缓存区framebuffer数组里*/
lv_res = lv_fs_read(&lv_file, framebuffer, 38400,&br);
testimg.data = framebuffer;
lv_img_set_src(imgBg, &testimg);
lv_obj_align(imgBg, NULL, LV_ALIGN_CENTER, 0, 0);
lv_task_handler();
/*7.将偏移往后加38404,就到了下一张图片*/
offset += 38404;
lv_res = lv_fs_seek(&lv_file, offset);
}
lv_fs_close(&lv_file);
|