stm32 播放高帧率高分辨率视频和照片详细制作过程(播放Bad Apple为例)

3 篇文章 0 订阅
2 篇文章 0 订阅

stm32 播放高帧率高分辨率视频和照片详细制作过程

下文以播放Bad Apple视频为例。

文章是我边调试边写的,质量不好请见谅。


所有资料都会总结好放到 网盘里,提取码:8e1z

更新:

其实格式工厂里就可以提取,真的是眼瞎没看到,浪费时间了。

但是这个生成出来的jpg文件,文件名格式是imgge_x.jpg,没有按照我们所学的0001-xxxx这样的格式,下面写一段python代码来改一下文件名字(太多了,不可能手改的)。

image-20220118235043712

import os
import re

path = "./badapple_800_480/" #图片文件夹的路径
pic_name_length = 13		#不需要修改的文件名长度,包括(.jpg)
pic_rename_format = "Image%04d.jpg" #需要修改的名字格式

def file_rename():
    suffix = 0
    files = os.listdir(path)
    # change current work path
    os.chdir(path)
    for file in files:
        file_name_size = len(file)
        if file_name_size < pic_name_length:
            # 获取数字
            if file.startswith("Image") and file.endswith(".jpg"):
                num = int(re.sub(r"Image", '', re.sub(".jpg", '', file)))
                #按照格式改名
                new_file_name = pic_rename_format % num
                os.rename(file, new_file_name)


file_rename()

硬件条件:

  • STM32H743IIT6核心板
  • TFT-LCD 800*480分辨率

方案一:

采用网上最通用的方法,将badapple视频处理为一帧一帧的图片,然后再将图片转化为一个个的bin文件,再合成为总的一个bin文件放到tf卡中,stm32按帧大小读bin文件,来显示图片。

**优点:**简单,适合小屏幕小性能的情况

**缺点:**显示的帧数低,大一点的屏幕就放不下。我采用的800*480的分辨率,rgb565的颜色格式。那一帧就是768000字节,bapapple视频有3.27分钟,也就是207秒。要实现一秒30帧率的效果的话。总的bin文件都已经超过了FAT32的最大文件限制4GB了(6210 * 76800),而且一秒30帧的话,也超出了tf卡读取的上限。

使用TouchGFX: 再弄TouchGFX的时候发现了它的L8RGB565格式,可以减小66%的bin文件大小,然后用TouchGFX的动画控件,设置固定的50ms切换图片的时间,再用上class10的高速tf卡,可能勉强能行。但是肯定不能做到我想要的800*480 30fps的效果。

方案二:

STM32H7性能强大,可以采用JPEG硬件解码的方法。配合上MDMA,DMA2D等硬件加速下,在RGB565和800*480的情况下跑个30pfs轻轻松松。实测下来,只要优化玩程序可以做到稳定60fps。

综上所述,采用方案二。

实现过程:

1.移植代码

每个人硬件不同,这里就不具体介绍实现过程。

由于stm32h7的特殊性,和f1 f4 f7完全不一样,sd卡的移植坑会比较多。

主要是由于h7内部的架构导致的,具体细节可以参考安富利的介绍。推荐用cubemx来移植jpeg+ltdc+sdmmc+fatfs+dma2d。

注意:

  • 我在这浪费了挺多时间,jpg文件不能太多,比如badappale视频3.27秒 30帧,那么就是6510张jpg图片,全部都放在sd卡的话,挂载文件系统,前几张图片读取会非常快,后面会越来越慢,这个问题最严重,导致我用了两天才弄完,本来半天就好了。
    • 解决方法:使用文件合并助手将全部jpg图片合成到一个文件里**(下文细讲)**。
  • tf卡一定要买class10的高速卡(普通卡读取速度差很多),sdmmc时钟可以调到高一点。
  • 移植的时候,要做好调试顺序
    • 解决方法:先弄sdmmc + fatfs,确保读文件速度。正常可以跑到10M/s+
    • sdram的移植,确保sdram的读和写正常
    • ltdc确保屏幕显示
    • dma2d,这个问题不大,使能时钟了就能用,正常使用都是直接调用寄存器。
  • jpeg问题也不大,使能初始化就行。

2.具体实现

在上面的硬件都移植完了后,就可以开始操作了。

2.1视频素材处理

这里采用的是matlab来处理视频文件,下面是代码:

资源路径自己修改。

% mp4 --> jpg
apple='H:\PersonalProducts\badapple\badapple_800_480.mp4';
obj = VideoReader(apple);
for i = 1 : 6510 %视频3分37秒,每秒30帧
    badApple = read(obj,i);
    imwrite(badApple,strcat('H:\PersonalProducts\badapple\output_jpg\badapple_',num2str(i,'%04d'),'.','jpg'));
end

2.2将图片合成到一个文件,并处理。

使用安富利的文件合并助手,非常nice一款软件。

**注意:**生成格式,选格式1,不要加逗号。

image-20220120135236723

将所有的jpg都合成到一个bin文件里了,那么每张图片我们如何知道长度和地址呢。

我们需要做一个存索引的文件,我这里做成Inde.txt,将输出的窗口数据复制到txt,然后保存好放到tf卡中。

坑点:
  • 最开始我采用的是格式2,不加逗号的格式输出。然后在stm32读取的时候花费了不少时间,fatfs没有一行一行读取,不像python有readline怎么方便。而且我们不知道每行的长度,类似下图。这就导致不能读一行出来后,取偏移地址,再取长度了。(最后勉强用这个实现了)

  • 如果输出格式1,不加逗号,那么格式都是一样的,如下图。每行长度确定,我们就可以一次固定读两行的长度。再取出两个16进制,前面的是起始地址,相减后就是所需读取的长度。

image-20220120140204068

image-20220120140430046

2.3读取文件

将合成的bin文件和索引文件都放到了sd卡后,就可以开始读bin文件了。

读取bin文件,需要一个bug,直接找jpg最大的图片,看它是多少自己就定义多少,一般就几十k。

然后上面说了读取索引文件的方法,就可以获取到索引地址和长度。

2.4JPEG硬件解码

将读取到的数据缓存和数据长度代入jpeg解码api接口,while()等待结束。

2.5DMA2D显示

将得到的YCbCr格式的图片数据,代入dma2d的api接口,即可显示。

最后根据所需的图片大小,循环调用即可显示一个视频。下面是我用格式2输出的代码,后面可以改成格式1的,直接采用我的这个必有问题。

for(i = 0; i < 6509; i++)
{
    iTimeStart = HAL_GetTick();
    f_open(&JPG_File,"0:index.txt",FA_OPEN_EXISTING | FA_READ);	//打开文件


    /* 更改索引,因为我这里采用格式2输出,导致下面的bug,采用格式1后会解决 */
    index_read_index = i*36 ;
    if(pic_size > 10000)offset += 1;index_read_index += offset;
    /* ******************************************************************* */        

    f_lseek(&JPG_File, index_read_index);   //更改索引
    f_read(&JPG_File, Index_Buffer, 37, &JPG_FileCount);  // 读取文件    算上换行回车,一行37个 从对应格式中获取长度
    f_close(&JPG_File);	  //关闭文件	
    sscanf(Index_Buffer, "0x%8x // Image%*d.jpg (%d)", &hexADDR, &pic_size);    //获取偏移和长度

    f_open(&JPG_File, "badapple_jpg.bin", FA_OPEN_EXISTING | FA_READ);
    f_lseek(&JPG_File, hexADDR);
    f_read(&JPG_File, JPG_FileBuffer, pic_size, &JPG_FileCount);  // 读取文件    一行36个 从对应格式中获取长度    
    f_close(&JPG_File);	  //关闭文件	

    JPEG_Decode_DMA((uint32_t)JPG_FileBuffer,pic_size, JPEG_OUTPUT_DATA_BUFFER);	// 调用DMA解码
    while( JPEG_Decode_WaitingforEnd() != DecodeComplete );		// 等待解码完成
    DMA2D_CopyBuffer( 0 , 0, (uint32_t *)JPEG_OUTPUT_DATA_BUFFER, (uint32_t *)LCD_FRAME_BUFFER );	// 使用DMA2D对解码后的图片进行显示

    iTimeEnd = HAL_GetTick();
    printf("%dmsd\r\n", (iTimeEnd - iTimeStart));    
}

3.性能测试

  • sd卡挂载fatfs后读取资源(0-2ms一次,具体看sd卡质量,和sdmms时钟)
  • jpeg硬件解码时间 800*480的分辨率下,仅需10ms左右,越小的图片越快。480 * 272试了下才3-4ms。
  • dma2d将转化完的结果,转化成rgb到屏幕上,大概12ms。

4.后期目标

  • 这方面弄好了后,如果后期使用gui,lvgl或者touchgfx的话,当成一个底层驱动移植好,就可以做到sd卡的图片浏览功能,sd卡中的视频播放功能**(注:需要上位机处理好的资源文件)**,gui中图片资源的转化,比bin文件的图片资源节省了数十倍的存储空间(速度上差距很小)。
  • 在上位机上做好jpeg解码,解码后的数据可以直接供给dma2d转化**(不是转化成rgb的bin资源)**,节省了转化的时间(小资源文件没必要,本来就1-2ms),这样读1-2ms,显示12ms,理论上来说可以稳定的做到60hz。

注意点:

**2.**本来一帧图片是768000的,但是他这个软件转换不了800 * 480,只有800 * 450那么也就是720000。这里被坑了下。

image-20220116112238980

3.使用网上采用的type会出现bug,和自己算出来的大小不一致,这里采用安富利的文件合并助手。

image-20220116141828259

**4.**视频转图片的是用的matlab,也可以自己改用python等等

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 要在STM32播放Bad Apple视频,您可以尝试以下步骤: 1. 将Bad Apple视频转换为适合STM32的格式,如RGB565格式的位图。您可以使用像FFmpeg这样的工具来完成此转换。 2. 将转换后的视频文件嵌入到STM32的Flash存储器中。您可以使用适当的软件工具,如ST-Link或J-Link,将视频文件下载到STM32的Flash存储器中。 3. 在STM32上编写播放Bad Apple视频的代码。您可以使用适当的STM32开发环境,如Keil或STM32CubeIDE,编写C语言代码来解码视频文件并将其显示在STM32的LCD屏幕上。 4. 通过与STM32的音频模块集成,添加音频输出来完善播放Bad Apple视频的体验。您可以使用PWM或DAC等技术来实现音频输出。 请注意,播放视频可能需要大量的存储器和处理器资源,因此您需要考虑STM32的处理能力和存储器容量是否足够。 ### 回答2: 近年来,stm32嵌入式系统在音视频处理方面的应用越来越广泛,而在音视频方面,Bad Apple(坏苹果)则是个非常典型的案。本文详细介绍了STM32播放Bad Apple的方法,供大家参考。 1、准备工作 (1)首先需要用一个相应的转换软件将从网络下载的Bad Apple MV视频转换成AVI或者MP4的文件格式。转换时尽量保证视频的质量,并将其存储在SD卡中,以便后续使用; (2)开始编写stm32程序之前,需要确认音频使用的是什么协议。一般情况下,我们可以选择像I2S协议,SPI I2S协议和SSI接口等方式来实现音频的输入输出; (3)如果要实现视频输出的效果,需要使用到TFT液晶,建议选用像ILI9341或SSD1963等,可以根据实际需求进行选择。 2、实现stm32播放Bad Apple (1)首先需要将视频读取进来,然后解码取出帧,显示单元格视频图像; (2)实现音频解码:将读取的音频进行解码,通过DAC等音频输出设备输出。 (3)实现音视频同步:在系统启动后,确定好解码速、音视频间的同步处理方式等,并使其同步。需要注意的是音视频同步时间不能出现误差,以确保最终播放效果的质量。 (4)实现视频输出:从SD卡中读出每一行像素的数据,将其处理成具有TFT显示器所需的格式,并将其输出至TFT液晶屏幕显示即可。 (5)完成音视频的输出之后,就可以实现整个系统的总控制,包括开机后自启动、暂停、继续等等。 总之,使用STM32播放Bad Apple不仅可以增加我们对STM32嵌入式系统的学习和应用经验,也可以深入了解到音视频数据的解码、同步和输出的相关知识。希望以上内容对大家能够提供一定的参考和帮助。 ### 回答3: STM32播放Bad Apple是一项非常有趣的任务。首先,我们需要了解Bad Apple视频文件的特点。Bad Apple视频文件是一种MPEG文件,它可以通过在STM32上解码和播放音频和视频来实现。解码需要一个解码器,而这个解码器需要一定的硬件资源和算法来支持。使用STM32F4作为主处理器可以使我们更快地处理视频数据。同时,使用TFT LCD可以更好地显示视频图像以及播放音频。 首先,我们需要找到一个类似于Bad Apple视频文件的MPEG文件。然后,我们需要使用一个解码器对该文件进行解码。在解码文件时,我们需要在STM32上分配一定的RAM来存储解码后的像素和音频数据。显然,解码器需要优化以尽可能少地使用RAM。一旦我们成功地解码了视频和音频数据,我们就需要将它们合并,以便可以同时播放音频和视频。 在播放音频和视频之前,我们需要初始化I2S接口。我们需要确保I2S接口的频与媒体文件的参数匹配。然后,我们需要使用I2S发送音频数据和STM32的DMA控制器来进行数据传输。这将确保我们在播放音频时获得最佳音质。 为了显示视频,我们需要使用TFT-LCD。我们需要使用类似于DMA的技术,使我们可以将像素数据直接传输到TFT-LCD。同时,我们需要优化像素数据以尽可能少地使用RAM。这将确保我们能够同时播放音频和视频。 综上所述,STM32播放Bad Apple需要我们深入理解媒体文件的结构,了解解码器和I2S接口的工作原理,以及掌握专业的编程技术。这可能需要一定的时间和精力,但这是一个非常有趣的任务。通过学习和实践,我们可以逐步掌握这些技能并实现STM32播放Bad Apple

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炒饭多加个蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值