1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html 4)对正点原子STM32感兴趣的同学可以加群讨论:879133275
第四十九章 硬件JPEG解码实验上一章,我们学习了图片解码,学会了使用软件解码显示bmp/jpg/jpeg/gif等格式的图片,但是软件解码速度都比较慢,本章我们将学习如何使用STM32H750自带的硬件JPEG编解码器,实现对JPG/JPEG图片的硬解码,从而大大提高解码速度。 本章分为如下几个小节: 49.1 硬件JPEG编解码器简介 49.2 硬件设计 49.3 程序设计 49.4 下载验证
49.1 硬件JPEG编解码器简介 STM32H750自带了硬件JPEG编解码器,可以实现快速JPG/JPEG编解码,本章我们仅使用JPG/JPEG解码器。STM32H7的JPEG编解码器具有如下特点: 支持JPEG编码/解码 支持RGB、YCbCr、YCMK与BW(灰度)色彩空间 单周期解码/编码一个像素 支持JPEG头数据编解码 多达4个可编程量化表 单周期哈夫曼表编解码 完全可编程的哈弗曼表(AC和DC各2个) 完全可编程的最小编码单元(MCU) 单周期哈弗曼编码/解码 49.1.1 JPEG编解码器框图 STM32H7的JPEG编解码器框图如图49.1.1.1所示:
图49.1.1.1 硬件JPEG编解码器框图 图中,硬件JPEG编解码器的输入和输出数据流都是通过32位AHB总线访问,其它的JPEG内部信号如下表所示:
表49.1.1.1 JPEG内部信号 49.1.2 JPEG解码器功能 我们只需要对JPEG编解码器的相关寄存器进行设置,然后读写输入/输出FIFO,即可完成JPEG的编解码。本章,我们只介绍如何利用STM32H7的硬件JPEG解码器实现对JPG/JPEG图片的解码。 硬件JPEG解码器,支持解码符合ISO/IEC10918-1协议规范的JPEG数据流,并且支持解码JPEG头(可配置),通过输入FIFO读取需要解码的JPEG数据,通过输出FIFO将解码完成的YUV数据传输给外部。 注意:硬件JPEG解码器解码完成后是YUV格式的数据,并不是RGB格式的数据,所以不能直接显示到LCD上面,必须经过YUVRGB的转换,才可以显示在LCD上面。 硬件JPEG解码时FIFO数据的处理(读取/写入)有两种方式: 1,中断方式。 2,DMA方式(JPEG编解码内核使用的是MDMA,下同!)。 为了达到最快的解码速度,我们一般使用DMA来处理FIFO数据。接下来,我们介绍一下硬件JPEG解码的数据处理过程。 1、输入FIFO MDMA 通过jpeg_ift_trg信号(对应MDMA数据流17,见《STM32H7xx参考手册_V7(英文版).pdf》第597页,Table 100),可以触发JPEG输入FIFO的MDMA请求,当输入FIFO(总容量为64字节)至少半空的时候,将产生一个MDMA请求,读取32字节数据到输入FIFO。当MDMA不再继续往JPEG输入FIFO传送数据时,JPEG解码进程将自动暂停,因此,我们只需要控制MDMA的启停,就可以控制JPEG的解码进程,这个操作在MDMA传输完成,读取下一批JPEG数据的时候经常用到。 注意:在当前图片解码完成后,开启下一张图片解码之前,需要先停止MDMA,然后对输入FIFO进行一次清空(设置JPEG_CR寄存器的IFF位),否则上一张图片的数据会影响到下一张图片的解码。 2、输出FIFO MDMA 通过jpeg_oft_trg信号(对应MDMA数据流19,见《STM32H7xx参考手册_V7(英文 版).pdf》第597页,Table 100),可以触发JPEG输出FIFO的MDMA,当输出FIFO(总容量为64字节)至少半满的时候,将产生一个MDMA请求,可以从输出FIFO读取32字节数据。当MDMA不再读取JPEG输出FIFO的数据时,JPEG输出FIFO被暂停,这个操作在MDMA传输完成,执行YUVRGB转换的时候经常用到。 注意:当图片解码结束以后,输出FIFO里面可能还有数据,此时我们需要手动读取FIFO里面的数据,直到JPEG_SR寄存器的OFNEF位为0。 3、JPEG头解码 通过设置JPEG_CONFR1寄存器的HDR位为1,可以使能JPEG头解码,通过设置JPEG_CR寄存器HPDIE位为1,可以使能JPEG头解码完成中断。在完成JPEG头解码之后,我们可以获取当前JPEG图片的很多参数,包括:颜色空间、色度抽样、高度、宽度和MCU总数等信息。这些参数对我们后面的解码和颜色转换(YUVRGB)非常重要。 硬件JPEG使用DMA实现JPG/JPEG图片解码的数据处理流程如图49.1.2.1所示:
图49.1.2.1 硬件JPEG解码数据处理流程(DMA方式) 由图可知,数据处理主要由2个MDMA完成:输入MDMA和输出MDMA,分别处理硬件JPEG的输入FIFO和输出FIFO的数据。通过适当控制输入MDMA/输出MDMA的关闭和重启,从而控制整个数据处理的进程,关闭MDMA的时间越少,解码速度就越快。 图中我们还用到了2个JPEG中断:JPEG头解析完成中断和JPEG解码完成中断,他们共用一个中断服务函数。JPEG头解析完成中断,在JPEG头解码完成后进入,此时我们可以获取JPG/JPEG图片的很多重要信息,方便后续解码。JPEG解码完成中断,在JPG/JPEG图片解码完成后进入,标志着整张图片解码完成。 49.1.3 MDMA简介 MDMA属于STM32H7内部4个DMA控制器之一,它的主要特点有: 支持3种传输方式:内存内存、内存外设、外设内存 支持多达16个通道 支持多达32个硬件触发源,且支持软件触发 所有通道都可以独立设置并连接到DMA1/DMA2或相关外设 一个256级深度buffer,被分成2个独立的128级buffer(先入/先出,即FIFO) 4个优先级可设置:非常高、高、中、低 源和目标的传输位宽可以独立设置(字节、半字、字、双字) 源地址/目标地址自增和大小都可以独立设置 我们重点看一下MDMA和DMA1/2的差异(DMA1/DMA2的详细介绍请参考第三十章 DMA实验),MDMA支持4种触发模式(通过TRGM[1:0]位设置),具体如下: 1、缓冲传输模式(最多一次可以传输128字节) 2、块传输模式(最多一次可以传输64K字节) 3、重复块传输模式(每次传输后,可配置改变源/目标的起始地址) 4、链表模式(直到各个信道数据传输完毕,比较复杂,一般不用) 而DMA1/DMA2只支持单次传输和突发传输,且突发传输仅支持4、8和16等个传输长度,本实验我们用MDMA的缓冲传输模式,因为JPEG的输入/输出FIFO每次都是读取/输出32字节,因此我们用缓冲模式(TRGM[1:0]=00),并设置单次触发传输长度为32字节(TLEN[6:0]=32-1),就可以很好的和JPEG的输入/输出FIFO匹配了。 关于MDMA的具体配置,我们在这里就不详细介绍了,MDMA的配置和DMA1/DMA2基本类似,不过稍微复杂一点。关于MDMA的详细介绍,请参考《STM32H7xx参考手册_V7(英文版).pdf》第14章。 49.1.4 YUV转RGB操作 在STM32F7系列MCU上面,要实现YUV到RGB的转换,必须使用纯软件的方式来实现,比较耗时间。但是到了H7系列MCU,ST添加了硬件YUV到RGB转换的功能,我们通过DMA2D可以很方便的实现YUV到RGB的硬件转换。 H7的DMA2D支持将:YCbCr 4:4:4(YUV444),4:2:2(YUV422)和4:2:0(YUV420)等三种抽样格式的颜色数据转换成RGB数据格式。DMA2D执行YCbCr数据格式转换的时候是以8*8的最小编码单元(MCU)为基础的,YCbCr数据在MCU内的排列顺序如下表所示:
图49.1.4.1 MCU中不同抽样方式下YCbCr的排列方式 由上表可知: YCbCr4:4:4(YUV444)抽样,每个RGB像素占3个YCbCr字节 YCbCr4:2:2(YUV422)抽样,每个RGB像素占2个YCbCr字节 YCbCr4:2:0(YUV420)抽样,每个RGB像素占1.5个YCbCr字节 为了保障DMA2D能够正确的执行YCbCr到RGB的转换,当图片采用:YCbCr 4:4:4的抽样方式时,图片宽度(DMA2D_NLR寄存器的PL[13:0]定义)+行偏移(DMA2D_FGOR寄存器的LO[15:0]定义)必须是8的倍数。当图片采用:YCbCr 4:2:2或YCbCr 4:2:0的抽样方式时,图片宽度(DMA2D_NLR寄存器的PL[13:0]定义)+行偏移(DMA2D_FGOR寄存器的LO[15:0]定义)必须是16的倍数。为了简化处理和节省内存,我们采用单幅图像,多次解码的方式来完成解码,因此规定:对于硬件JPEG解码的图片,其宽度必须是16的倍数。 DMA2D执行内存到内存的YCbCrRGB转换的简要设置(行偏移为0)如下: 1,设置DMA2D_CR寄存器的MODE[2:0]=001,DMA2D工作在带PFC的存储器到存储器模式。 2,设置DMA2D_OPFCCR的CM[2:0]=010,设置PFC输出图像格式为:RGB565。 3,设置DMA2D_FGPFCCR的CSS[1:0]为正确的抽样方式(YCbCr 4:4:4/4:2:2/4:2:0,根据实际情况设置),并设置CM[3:0]=1011,设置输入图像格式为:YCbCr。 4,设置DMA2D_NLR的PL[13:0]为图像宽度(必须为16的倍数),NL[15:0]为单次转换输出的图像高度(YCbCr 4:4:4和YCbCr 4:2:2每次输出8的倍数行,YCbCr 4:2:0每次输出16的倍数行)。 5,设置DMA2D_OMAR的MA[31:0]为输出图像数据的首地址。该地址需根据单次输出的图像高度和宽度,进行变化,以完成整幅图像的输出。 6,设置DMA2D_FGMAR的MA[31:0]为输入图像数据的首地址。另外,单次输入图像数据的大小,是有要求的。输入图像是YCbCr数据格式,根据前面的介绍,不同抽样率下,最小输入图像数据的大小为: 单次输出行数YCbCr每个像素所占字节数图像宽度 对于YCbCr 4:4:4,最小输入图像数据大小为:83图像宽度 对于YCbCr 4:2:2,最小输入图像数据大小为:82图像宽度 对于YCbCr 4:2:0,最小输入图像数据大小为:161.5图像宽度 7,最后,设置DMA2D_CR寄存器的START位为1,使能DMA2D传输。然后等待传输完成就可以完成一次YCbCrRGB的转换。 以上,就是利用DMA2D进行YCbCr到RGB图像数据转换的简要设置,DMA2D的相关寄存器我们这里就不做介绍,详见《STM32H7xx参考手册_V7(英文版).pdf》第18章相关章节。 49.1.5 JPEG编解码器寄存器 下面介绍本实验需要用到的JPEG 编解码器寄存器。 JPEG编解码器控制寄存器0(JPEG_CONFR0) 该寄存器仅最低位(START位)有效,设置该位为1,可以启动JPEG解码流程。通过设置该位为0,可以退出当前JPEG解码。 JPEG编解码器配置寄存器1(JPEG_CONFR1) JPEG编解码器配置寄存器1描述如图49.1.5.1所示:
图49.1.5.1 JPEG_CONFR1寄存器 YSIZE[15:0]位,定义JPEG图片的高度,读取该寄存器可以获得图片高度(注意:需要在JPEG头解析成功以后,才可以读取该寄存器获取图片高度,下同)。 HDR位,用于设置是否使能JPEG头解码,我们一般设置为1,使能JPEG头解码。 DE位,用于设置硬件JPEG工作模式,我们设置为1,表示使用JPEG解码模式。 NF[1:0]位,这两个位用于定义色彩组成:00,表示灰度图片;01,未用到;10,表示YUV/RGB;11表示CYMK。 JPEG编解码器配置寄存器3(JPEG_CONFR3) JPEG编解码器配置寄存器3描述如图49.1.5.2所示:
图49.1.5.2 JPEG_CONFR3寄存器 该寄存器仅高16位(YSIZE[15:0])有效,定义JPEG图片的宽度,读取该寄存器可以获得图片宽度。 另外,还有JPEG配置寄存器47:JPEG_CONFR47,这四个寄存器ST官方数据手册对其解释也不是很清楚,但是我们可以参考ST官方提供的参考代码,知道这四个寄存器的NB[3:0]位用来表示YUV的抽样方式(YUV422、YUV420、YUV444),详见本例程源码。 JPEG控制寄存器(JPEG_CR) JPEG控制寄存器描述如图49.1.5.3所示:
图49.1.5.3 JPEG_CR寄存器 OFF位,用于清空输出FIFO,在启动新图片解码之前,需要对输出FIFO进行清空。 IFF位,用于清空输入FIFO,在启动新图片解码之前,需要对输入FIFO进行清空。 HPDIE位,用于使能JPEG头解码完成中断,我们设置为1,使能JPEG头解码完成中断,在中断服务函数里面读取JPEG的相关信息(长宽、颜色空间、色度抽样等),并根据色度抽样方式,获取对应的YUVRGB转换函数。 EOCIE位,用于使能JPEG解码完成中断,我们设置为1,使能JPEG解码完成中断,在中断服务函数里面标记JPEG解码完成,以便结束JPEG解码流程。 JCEN位,用于使能硬件JPEG内核,我们必须设置此位为1,以启动硬件JPEG内核。 JPEG状态寄存器(JPEG_SR) JPEG状态寄存器描述如图49.1.5.4所示:
图49.1.5.4 JPEG_SR寄存器 HPDF位,表示JPEG头解码完成的标志,当该位为1时,表示JPEG头解析成功,我们可以读取相关寄存器,获取JPEG图片的长宽、颜色空间和色度抽样等重要信息。向JPEG_FCR寄存器的CHPDF位写1,可以清零此位。 EOCF位,表示JPEG解码结束标志,该位为1时,表示一张JPEG图像解码完成。此时我们可以从输出FIFO读取最后的数据。向JPEG_FCR寄存器的CEOCF位写1,可以清零此位。 JPEG清零标志寄存器(JPEG_CFR) JPEG清零标志寄存器描述如图49.1.5.5所示:
图49.1.5.5 JPEG_CFR寄存器 该寄存器,仅两位有效:CHPDF位和CEOCF位,向这两个位写入1,可以分别清除JPEG_SR寄存器的HPDF和EOCF位。 最后是JPEG数据输入寄存器(JPEG_DIR)和JPEG数据输出寄存器(JPEG_DOR),这两个寄存器都是32位有效,前者用于往输入FIFO写入数据。后者用于读取输出FIFO的数据。 49.2 硬件设计
- 例程功能 1、本实验开机的时候先检测字库,然后检测SD卡是否存在,如果SD卡存在,则开始查找SD卡根目录下的PICTURE文件夹,如果找到则显示该文件夹下面的图片文件(支持bmp、jpg、jpeg或gif格式),循环显示,通过按KEY0和KEY1可以快速浏览下一张和上一张,KEY_UP按键用于暂停/继续播放,LED1用于指示当前是否处于暂停状态。如果未找到PICTURE文件夹/任何图片文件,则提示错误。 注意:本例程的实验现象,同上一章(图片显示实验)完全一模一样,唯一的区别,就是JPEG解码速度 (要求图片分辨率小于等于LCD分辨率) 变快了很多。 对比上一章的图片显示,大家可以利用USMART测试同一张JPEG图片,软件解码和硬件解码的时间差距。本实验也可以通过USMART调用ai_load_picfile和minibmp_decode解码任意指定路径的图片。 2、LED0闪烁,提示程序运行。
- 硬件资源 1)RGB灯 RED :LED0 - PB4 GREEN :LED1 - PE6 2)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面) 3)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动) 4)独立按键 :KEY0 - PA1、KEY1 - PA15、WK_UP - PA0 5)SD卡,通过SDMMC1(SDMMC_D0D4(PC8PC11), SDMMC_SCK(PC12),SDMMC_CMD(PD2))连接 6)norflash(QSPI FLASH芯片,连接在QSPI上) 7)硬件JPEG解码内核(STM32H750自带) 49.3 程序设计 49.3.1 硬件JPEG解码JPG/JPEG的简要步骤 为了提高速度,我们直接操作寄存器,没有使用HAL库提供的函数。 所以HAL库的内容就讲解了,接下来,我们看看在DMA模式下,使用STM32H7的硬件JPEG解码JPG/JPEG的简要步骤: 1)初始化硬件JPEG内核。 首先,我们通过设置AHB3ENR的bit5位为1,使能硬件JPEG内核时钟,然后通过JPEG_CR寄存器的JCEN位,使能硬件JPEG。通过清零JPEG_CONFR0寄存器的START位,停止JPEG编解码进程。通过设置JPEG_CONFR1寄存器的HDR位,使能JPEG头解码。最后设置JPEG中断服务函数的中断优先级,完成初始化硬件JPEG内核过程。 2)初始化硬件JPEG解码。 在初始化硬件JPEG内核以后,我们配置JPEG内核工作在JPEG解码模式。通过设置JPEG_CONFR1寄存器的DE位,使能JPEG解码模式。然后设置JPEG_CR寄存器的OFF、IFF、HPDIE、EOCIE等位,清空输出/输入FIFO,并开启JPEG头解码完成和JPEG解码完成中断。最后,设置JPEG_CONFR0寄存器的START位,启动JPEG解码进程。 注意:此时我并未开启JPEG的输入和输出MDMA,只要我们不往输入FIFO写入数据,JPEG内核就一直处于等待数据输入状态。 3)配置硬件JPEG输入/输出MDMA。 这一步,我们将配置JPEG的输入MDMA和输出MDMA,分别负责JPEG输入FIFO和输出FIFO的数据传输。对于输入MDMA,目标地址为JPEG_DIR寄存器地址,源地址为一片内存区域,利用输入MDMA实现JPEG输入FIFO数据的自动填充。对于输出MDMA,目标地址为一片内存区域,源地址为JPEG_DOR寄存器地址,利用输出MDMA实现JPEG输出FIFO数据自动搬运到对应内存区域。对于输入MDMA和输出MDMA,我们都需要开启传输完成中断,并设置相关中断服务函数。在传输完成中断里面,实现对输入输出数据的处理。 4)编写相关中断服务函数,启动MDMA。 我们总共开启了4个中断:JPEG头解码完成中断、JPEG解码完成中断、输入MDMA传输完成中断和输出MDMA传输完成中断。前两个和后两个中断分别共用一个中断服务函数,所以我们总共只需要编写2个中断服务函数。另外,我们采用回调函数的方式,对数据进行处理,总共需要编写4个回调函数,分别对应4个中断产生时的数据处理。在配置完这些以后,启动MDMA,开始执行JPEG解码。 注意:输出MDMA的配置和启动,我们放在JPEG头解码完成中断回调函数里的,因为输出YCbCr数据的多少和单次输出行数,得根据抽样方式进行不同的设置,因此我们必须先等到解析完JPEG头以后,再来配置输出MDMA。 5)处理JPEG数据输出数据,执行YUVRGB转换,并送LCD显示。 最后,在主循环里面,根据输入MDMA和输出MDMA的数据处理情况,持续从源文件读取JPEG数据流,并利用DMA2D,将硬件JPEG解码完成的YCbCr(YUV)数据流转换成RGB格式。最后,在完成一张JPEG解码之后,将RGB数据直接一次性显示到LCD屏幕上,实现图片显示。 49.3.2 程序流程图
图49.3.2.1 硬件JPEG解码实验程序流程图 49.3.3 程序解析
- JPEGCODEC驱动代码 这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。JPEGCODEC驱动源码包括两个文件:jpegcodec.c和jpegcodec.h。 jpegcodec.h头文件定义了两个结构体和一些宏定义,下面重点围绕jpeg_codec_typedef这个结构体介绍一下,jpegcodec.h的相关内容定义如下:
#define JPEG_DMA_INBUF_LEN 4096 /* 单个MDMA IN BUF的大小 */
#define JPEG_DMA_INBUF_NB 10 /* MDMA IN BUF的个数 */
#define JPEG_DMA_OUTBUF_NB 2 /* MDMA OUT BUF的个数 */
/* JPEG数据缓冲结构体 */
typedef struct
{
uint8_t sta; /* 状态:0,无数据;1,有数据 */
uint8_t *buf; /* JPEG数据缓冲区 */
uint16_t size; /* JPEG数据长度 */
} jpeg_databuf_type;
#define JPEG_STATE_NOHEADER 0 /* HEADER未读取,初始状态 */
#define JPEG_STATE_HEADEROK 1 /* HEADER读取成功 */
#define JPEG_STATE_FINISHED 2 /* 解码完成 */
#define JPEG_STATE_ERROR 3 /* 解码错误 */
#define JPEG_YCBCR_COLORSPACE JPEG_CONFR1_COLORSPACE_0
#define JPEG_CMYK_COLORSPACE JPEG_CONFR1_COLORSPACE
/* jpeg编解码控制结构体 */
/typedef struct
{
JPEG_ConfTypeDef Conf; /* 当前JPEG文件相关参数 */
jpeg_databuf_type inbuf[JPEG_DMA_INBUF_NB]; /* MDMA IN buf */
jpeg_databuf_type outbuf[JPEG_DMA_OUTBUF_NB]; /* MDMA OUT buf */
volatile uint8_t inbuf_read_ptr; /* MDMA IN buf当前读取位置 */
volatile uint8_t inbuf_write_ptr; /* MDMA IN buf当前写入位置 */
volatile uint8_t indma_pause; /* 输入MDMA暂停状态标识 */
volatile uint8_t outbuf_read_ptr; /* MDMA OUT buf当前读取位置 */
volatile uint8_t outbuf_write_ptr; /* MDMA OUT buf当前写入位置 */
volatile uint8_t outdma_pause; /* 输入MDMA暂停状态标识 */
volatile uint8_t state;/* 解码状态;0,未识别到Header;1,识别到了Header;2,解码完成*/
/* YUV输出的字节数,使得完成一次DMA2D YUV2RGB转换,刚好是图片宽度的整数倍
* YUV420图片,每个像素占1.5个YUV字节,每次输出16行,yuvblk_size=图片宽度*16*1.5
* YUV422图片,每个像素占2个YUV字节和RGB565一样,每次输出8行,yuvblk_size=图片宽度*8*2
* YUV444图片,每个像素占3个YUV字节,每次输出8行,yuvblk_size=图片宽度*8*3 */
uint32_t yuvblk_size;
/* 每个YUV块输出像素的高度,对于YUV420,为16,对于YUV422/YUV444为8 */
uint16_t yuvblk_height;
uint16_t yuvblk_curheight; /* 当前输出高度,0~分辨率高度 */
} jpeg_codec_typedef;
该结构体用于控制整个JPEG解码,下面分别介绍一下它的成员:
Conf用于存储当前JPEG文件的一些相关信息,其结构体类型定义如下:
/* JPEG文件信息结构体 */
typedef struct
{
u8 ColorSpace; /* 图像的颜色空间: gray-scale/YCBCR/RGB/CMYK */
/* YCBCR/CMYK颜色空间的色度抽样情况: 0:4:4:4; 1:4:2:2; 2:4:1:1; 3:4:2:0 */
u8 ChromaSubsampling;
u32 ImageHeight; /* 图像高度 */
u32 ImageWidth; /* 图像宽度 */
u8 ImageQuality; /* 图像编码质量:1~100 */
}JPEG_ConfTypeDef;
inbuf和outbuf分表代表输入MDMA FIFO和输出MDMA FIFO,使用FIFO来处理MDMA数据,可以提高读写效率。注意:这里的输入MDMA FIFO和输出MDMA FIFO同JPEG的输入FIFO和输出FIFO是不一样的,要注意区分。通过JPEG_DMA_INBUF_NB和JPEG_DMA_OUTBUF_NB宏定义,我们可以修改输入DMA FIFO和输出DMA FIFO的深度。 其它,还有输入输出MDMA FIFO的读写位置、暂停状态、解码状态、单次YUV输出字节数、单次输出图像高度和当前输出高度等信息。 下面开始介绍jpegcodec.c文件,首先是JPEG规范(ISO/IEC 10918-1标准)的样本量化表,其定义如下: /* JPEG规范(ISO/IEC 10918-1标准)的样本量化表
- 获取JPEG图片质量时需要用到
*/
const uint8_t JPEG_LUM_QuantTable[JPEG_QUANT_TABLE_SIZE] =
{
16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99
};
const uint8_t JPEG_ZIGZAG_ORDER[JPEG_QUANT_TABLE_SIZE] =
{
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};
这两个数组在后面的jpeg_get_quality函数,获取JPEG图片质量时需要用到。 下面介绍的是JPEG硬件解码输入MDMA配置函数,其定义如下:
/**
* @brief JPEG硬件解码输入MDMA配置
* @param meminaddr : JPEG输入MDMA存储器地址
* @param meminsize : 输入MDMA数据长度,0~262143,以字节为单位
* @retval 无
*/
void jpeg_in_dma_init(uint32_t meminaddr, uint32_t meminsize)
{
uint32_t regval = 0;
uint32_t addrmask = 0;
RCC->AHB3ENR |= 1 CCR & 0X01); /* 等待MDMA_Channel7关闭完成 */
MDMA_Channel7->CIFCR = 0X1F; /* 中断标志清零 */
MDMA_Channel7->CCR |= 1 DIR; /* 目标地址为:JPEG->DIR */
MDMA_Channel7->CSAR = meminaddr; /* meminaddr作为源地址 */
regval = 0
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?