转 STM32+SD卡+znFAT+TFT液晶+AVI视频解码 实现“简易视频播放器”

2019-08-08 12:41发布


http://bbs.21ic.com/frame.php?frameon=yes&referer=http%3A//bbs.21ic.com/icnewest.html









  振南znFAT 单片机上的FAT32文件系统

关注znFAT,加入QQ群 106889506

1.JPG 下载 (21.72 KB)
2012-8-26 22:00 2.JPG 下载 (22.24 KB)
2012-8-26 21:57 3.JPG 下载 (12.02 KB)
2012-8-26 21:57 4.JPG 下载 (17.04 KB)
2012-8-26 21:57 5.JPG 下载 (10.18 KB)
2012-8-26 21:57 6.JPG 下载 (10.06 KB)
2012-8-26 21:57
====================================
IMG_0750.gif 下载 (344.75 KB)
2012-8-26 22:00 IMG_0750-[0002].gif 下载 (487.05 KB)
2012-8-26 22:00
====================================
相关软件:FFDSHOW解码器包:http://58.51.84.4:82/down/ffdshow_beta7_rev3154_20091209.zip
      实验演示视频录像:
====================================
     在我们拿到一个液晶显示模块,尤其彩 {MOD}液晶屏的时候,你有没有想过用它作一个图片显示,甚至是视频播放的实验呢?也许你在实现的过程中遇到了重重困难。振南在这里所作的“简易视频播放器”实验希望能给你一个参考。
     我们知道要在液晶上显示一些图案,我们就要将像素数据写到液晶的显示缓冲区(CGRAM)之中。比如对于一个16位 {MOD}(可显示6万5千种颜 {MOD})的彩 {MOD}液晶来说,它的每一个像素都对应于一个16位的RAM单元,通过它来设定这个像素所显示的颜 {MOD}。(我们在此实验中所使用的TFT液晶就是一个16位 {MOD}的液晶,颜 {MOD}表示的形式为RGB565,即在16位的数码中,高5位用于表达红 {MOD}分量、中间6位用于表达绿 {MOD}分量、低5位用于表达蓝 {MOD}分量。)
视频播放实验1-310.png 下载 (62.93 KB)
2012-8-26 22:00

     只要我们向液晶的每一个像素写入相应的数据,最终我们就可以让液晶显示出相应的图案。比如上图,我们就显示了一幅美女图(其实长得比我老婆差远了)。至于图片上各个像素的RGB565的数值如何获取?我们可以使用Image2LCD这个软件来得到,想必很人都已经用过。通常这些像素数据我们是以数组的形式固化在单片机的ROM中的。

  1. const unsigned char pimage[IMAGE_SIZE] =
  2. {
  3. 0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,
  4. 0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,
  5.   ......//很多的像素数据
  6. 0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,
  7. 0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,
  8. };
复制代码 好,你已经知道如何在液晶上显示一幅图像了。那“视频播放”的原理就不难理解了:把视频的每一帧图像按顺序依次显示在液晶上,只要速度够快,我们就可以看到连贯的动画效果,这就是“视频”了!
     现在的问题是:我们如何获取这一帧又一帧的视频图像数据?也许你会说:可以在视频文件中去获取这些图像数据吧?比如平常我们所熟悉的AVI、MP4、RMVB等等,它们之中肯定存着图像的数据和信息。没错,每一帧的图像数据就在其中,但是却没那么容易得到可以用于显示的RGB565数据。因为这些视频帧经过了某种压缩算法的编码,已经面目全非,而且这种压缩算法可能会极为复杂而强劲,要想得到RGB565的像素数据,必须要把这些数据经过“逆向算法”进行还原,这就是视频的解码。
     其实,我们会发现,很多人在用液晶显示图片的时候,都喜欢用BMP这种文件格式,这是因为BMP中存储的就是现成的RGB数据,而没有经过任何的压缩处理(有些特殊的BMP可能也有压缩,但通常是没有的),我们通常称这种数据为Raw Data,即原始数据。正是因为没有经过压缩处理,所以我们会发现BMP文件的数据量是比较大的。所以,我们只需要直接读取BMP的数据,不经任何处理就可以用于显示了。
     在前面,我发布的“简单数码相机”实验中,我所使用的就是BMP图像格式,因为它简单,直接把从摄像头得到的RGB数据“扔”到文件里就可以了!
     其实,单单就图片文件来说,就有很多种格式,比如JPG、PNG、GIF等等。它们也是经过了压缩算法处理过的,所以很少有人去直接使用这些图片文件。其实我们就是通过借助Image2LCD这个工具来对图片进行了解码,从而获得像素数据的。这个通过软件工具获取像素数据的过程,我们也称为“取模”!(当然我们也经常会看到有一些高手,在一些单片机或处理器上直接对这些图像格式进行解码,这就要考验算法和数字信号处理的一些功底了,同时也需要性能比较高的CPU)。
     要用单片机或者处理器,直接对视频进行解码,难度是很大的。那在电脑上有没有一种软件可以把视频文件转换为像素数据,就像是Image2LCD软件那样将各种图片转为像素数据数组那样。答案是没有!至少我还没有发现有这样的软件。其实就算有,转换后的像素数据量也比单单一幅图像的数据量要大得多,我们的单片机哪有那么大的ROM去固化这些像素数据?为了存储如此大的数据量,所以我们使用SD卡
视频播放实验1-1853.png 下载 (8.33 KB)
2012-8-26 22:00

     既然没有现成的视频解码软件来为我们提供像素数据,那我们就自己来写一个软件。使用VC6.0+VFW(VFW是Windows上的一套基于AVI视频的编解码开发包,可以让我们很轻松完成对AVI视频的编解码工作,详细请见http://baike.baidu.com/view/189682.htm)。振南已经实现了这个软件,我们来看一下它的用法(在使用此软件前,请先安装ffdshow解码器包,以保证各种AVI格式都可以正常解码)。
视频播放实验1-2068.png 下载 (58.54 KB)
2012-8-26 22:00

     我们可以通过这个软件来获取一个AVI视频的某一段视频各帧图像的RGB565数据,同时可以调整视频尺寸,比如缩放系数为2,则一个320X240的视频,将缩小为160X120;此缩放系数也支持小数,比如为2.5,则视频尺寸将缩小为128X96;如果此系数小于1,则是对视频尺寸的放大,比如为0.5,则视频尺寸扩大为640X240。还可以设置帧步进的值来调整视频的帧频,比如一个视频每秒有30帧图像,如果帧步为2,则帧步将降为15。
     为了记录解码之后的每帧图像的RGB565像素数据,也为了方便单片机读取像素数据,振南定义了这样一种文件格式,名为ZNV
视频播放实验1-2345.png 下载 (15.31 KB)
2012-8-26 22:00

     ZNV文件格式的最开始记录了转换之后的每一幅图像的尺寸,即高与宽,以及此文件中所记录的图像(即视频帧)的总数量。随后就是依次存放各图像的RGB565像素数据。最终得到的znv文件,放到SD卡上,由单片机或处理器读取SD卡上的znv文件中的图像数据,送到TFT液晶显示,从而完成简易的视频播放实验。(其实大家会发现,早期的MP4视频播放器,很多也是需要在PC上进行格式的转换的,而且MP4视频播放器所支持的格式也很少。这主要就是受限于主控芯片的处理能力,达不到一些视频解码所需要的硬件性能。或者是因为一些视频格式的版权问题,比如RMVB。如今,MP4播放器基本上都能支持大部分的视频格式了,而不用再用PC进行转换,主要还是因为主控芯片的性能提升了。)
     现在问题又来了!记录着每一帧图像像素数据的ZNV文件已经放在SD卡上了。单片机要如何来读取它的数据?对,就如上图的图中所示的,要使用znFAT了。SD卡要存储文件,都必须要进行格式化,通常我们使用FAT32文件系统所谓文件系统,其实就是一种数据管理的方式。ZNV文件的数据通过FAT32文件系统存放到了SD卡的某些扇区之中。单片机要想读到文件的数据,就必须要遵循FAT32的一些协议与定义。振南长期研究和编写的znFAT,就是这样一种与FAT32高度兼容的文件系统方案。它可以让单片机和各种处理器,很轻松的完成对文件的操作。【关于振南的znFAT,详细请参见znFAT应用手册】
     为了使视频播放的效果比较流畅,我们使用STM32(具体型号为STM32F103RBT6)作为核心CPU,完成znFAT文件系统的运行、文件数据的读取、TFT液晶的驱动等。
     【同时,文件数据的读取速度也是视频播放是否流畅的重要因素。这对于znFAT的效率性能与数据操作速度是一个挑战。】
视频播放实验1-3049.png 下载 (38.04 KB)
2012-8-26 22:00

在STM32上使用znFAT读取znv文件数据,送给TFT液晶的主要代码如下:
视频播放实验1-3091.png 下载 (33.91 KB)
2012-8-26 22:00






实验演示视频录像:
http://v.youku.com/v_show/id_XNDQzNTQ3MTg4.html
http://v.youku.com/v_show/id_XNDQzNTA1MzU2.html
http://v.youku.com/v_show/id_XNDQzMDY3NjI4.html
====================================

                                 

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
骤雨龙元
1楼-- · 2019-08-09 03:55
他是把视频转为RAW,那个数据量之大不可想像.
keyway
2楼-- · 2019-08-09 07:40

#ifndef _GIF_H_
#define _GIF_H_

#define GIF_GLOBAL_SIZE 13  //文件頭長度
#define GIF_PALETTE_SIZE 768//顏 {MOD}列表最大長度
#define GIF_LOCAL_SIZE   9 //局部圖形數據頭長度
#define GIF_DATA_MAX 512 //每次為數據緩衝區開闢258字節的空間
//文件頭:
typedef struct tagGlobal {
    char magic_word[3];//文件標誌 gif
    char version[3];//文件版本號 87a / 89a
    short width;// 邏輯屏幕寬度
    short height;// 邏輯屏幕高度
    unsigned char flag;// m  cr  s  pixel (m 全局顏 {MOD}列表標緻1bit  cr+1  顏 {MOD}深度3bit  //s 分類標緻,若為1表示顏 {MOD}表分類排列1bit pixel 全局顏 {MOD}列表大//小3bit,顏 {MOD}表大小 =3 * 2 ^(pixel +1))
    unsigned char bg_color;//背景顏 {MOD}序號
    unsigned char aspect;// 象素寬高比
}gif_global_t;

//顏 {MOD}列表:顏 {MOD}列表由文件解析程序在解析文件時動態申請
typedef struct tagPalette {
unsigned char *palette[255];
unsigned char num;
}gif_palette_t;

//局部數據塊頭信息  標緻 0x2C
typedef struct tagLocal {
    short x;// X方向偏移
    short y;// Y方向偏移
    short width;// 圖像寬度
    short height;// 圖像高度
unsigned char flag;// m i s r pixel (m 局部顏 {MOD}列表標緻1bit i 交織標緻1bit s 分類標誌//1bit r 2bit pixel 3bit)
}local_t;

typedef struct _local_2c
{
    local_t gif_local_title;//局部文件數據頭信息
unsigned char paleIndex;//顏 {MOD}列表的序號
unsigned char contrIndex;//使用控制塊序號
unsigned char *gif_loca_data;//圖形數據存放緩衝區指針
short datablockNum;//數據塊數目  每分配一個圖形數據存放緩衝區該值加1
int          dataSum;//記錄數據總數
unsigned char codeFlag;//數據解碼標緻   codeFlag .7 ---- 為1數據已解碼
}_2c;


typedef struct
{
  _2c * local_2c[255];
  unsigned char num;
}_local_2c;


//各擴展塊數據
//_01  --圖形文本擴展
typedef struct  __01
{
   unsigned char blockLen;//塊大小  固定為12
   unsigned char blockData[12];//快數據
   unsigned char *bloackText;//文本指針  第一個字節為文本長度
}_01;

typedef struct
{
  _01 * Extern_01[255];
  unsigned char num;
}local_Extern_01;


//_f9 --圖形控制擴展
typedef struct __f9
{
   unsigned char blockLen;//塊大小  固定為4
   unsigned char blockData[4];//快數據
}_f9;

typedef struct
{
  _f9 * Extern_f9[255];
  unsigned char num;
}local_Extern_f9;

//_fe --註釋擴展
typedef struct __fe
{
   unsigned char *bloackText;//註釋文本指針  第一個字節為文本長度
}_fe;

typedef struct
{
  _fe * Extern_fe[255];
  unsigned char num;
}local_Extern_fe;




//_ff --應用程序擴展
typedef struct __ff
{
   unsigned char blockLen;//塊大小  固定為11
   unsigned char blockData[11];//快數據
   unsigned char *bloackText;//文本指針  第一個字節為文本長度
}_ff;

typedef struct
{
  _ff * Extern_ff[255];
  unsigned char num;
}local_Extern_ff;

//解壓參數
typedef struct tagCode {
    char first;
    char last;
    int  prefix;
}gif_code_t;

//總體結構
typedef struct tagGifInfo {
gif_global_t  gif_global;
  gif_palette_t gif_global_palette;
  unsigned char paleIndex;//全局顏 {MOD}顏 {MOD}列表的序號
_local_2c   gif_local_2c;
  local_Extern_01  gif_local_Extern_01;
  local_Extern_f9  gif_local_Extern_f9;
  local_Extern_fe  gif_local_Extern_fe;
  local_Extern_ff  gif_local_Extern_ff;

int gif_buffer_length;
unsigned char* gif_buffer;
unsigned char* gif_cur_buffer;

gif_code_t code_table[4096];
unsigned char code_string[1024];

int code_limit;
int b_local_palette;
int b_interlaced;

int request_bits;
int first_ch;

int pass;
int code;
int prefix;

int free_code;
int EOI,CLEAR;

  int remain_bytes;
  int remain_bits;
  char unsigned data;

unsigned char* gif_surface;
int gif_x;
int gif_y;
}gif_info_t;


#define gifMax 10
#define flashtime 100
typedef struct
{
gif_info_t *gifPtr;//gif文件指針
char filename[10];//gif文件名
int x;//GIF顯示時相對LCD的偏移x地址
int y; //GIF顯示時相對LCD的偏移y地址
unsigned index;//圖片顯示次序
GUI_MEMDEV_Handle hMem;
   WM_HWIN _WM_1;
unsigned char flag;//0x00 未裝載   0x01  已裝載但不顯示  0x81正在顯示
}_gif_;

typedef struct
{
   _gif_ *gifPPtr[gifMax];
   unsigned char  num;//記錄當前裝載的數目
   unsigned char flag;//初始化標誌  88--表示已初始化
}_gif;


 
#endif

正点原子
3楼-- · 2019-08-09 09:44
这个有点像PIC那个gif解码的库代码。
sky3344
4楼-- · 2019-08-09 10:08
 精彩回答 2  元偷偷看……
beyond696
5楼-- · 2019-08-09 14:17
回复【4楼】sky3344:
---------------------------------
不知道你了解过gif没有,完全不同的东西
HEHEHE
6楼-- · 2019-08-09 17:54
都是大神,,小弟还处于潜水论坛 默默倾听阶段

一周热门 更多>