让mini2440播放视频(简易版)

时间:2022-04-24 20:07:03

mini2440附赠光盘\非操作系统示例代码\下有一个测试项目2440test,只要对该项目略作修改就能,让板子播放视频了(超简易方案,还有其他不少缺陷,高手们不要来喷我啊。。。)

主要修改了两处代码,把暂时不用的功能删掉了,修改过的程序如下:

#defineGLOBAL_CLK1

//#include <stdlib.h>
//#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"

extern void TFT_LCD_Init(void);
extern void TFT_LCD_Test(void);
volatile U32 downloadAddress;
volatile U32 downloadFileSize;

static U32 cpu_freq;
static U32 UPLL;
static void cal_cpu_bus_clk(void)
{
U32 val;
U8 m, p, s;

val = rMPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;

//(m+8)*FIN*2 不要超出32位数!
FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;

val = rCLKDIVN;
m = (val>>1)&3;
p = val&1;
val = rCAMDIVN;
s = val>>8;

switch (m) {
case 0:
HCLK = FCLK;
break;
case 1:
HCLK = FCLK>>1;
break;
case 2:
if(s&2)
HCLK = FCLK>>3;
else
HCLK = FCLK>>2;
break;
case 3:
if(s&1)
HCLK = FCLK/6;
else
HCLK = FCLK/3;
break;
}

if(p)
PCLK = HCLK>>1;
else
PCLK = HCLK;

if(s&0x10)
cpu_freq = HCLK;
else
cpu_freq = FCLK;

val = rUPLLCON;
m = (val>>12)&0xff;
p = (val>>4)&0x3f;
s = val&3;
UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
}

void Main(void)
{

U32 mpll_val = 0 ;
Port_Init();
mpll_val = (92<<12)|(1<<4)|(1);

ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
ChangeClockDivider(14, 12);
cal_cpu_bus_clk();

Beep(2000, 100);

MMU_Init();//

Led_Display(0x66);

TFT_LCD_Init();
TFT_LCD_Test();

}


/**************************************************************
The initial and control for 640×480 16Bpp TFT LCD----VGA
**************************************************************/

#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"


extern const unsigned char sunflower_320x240[];
extern const unsigned char sunflowers3[][153600];//18帧
extern const unsigned char sunflowers4[][153600];//18帧
extern const unsigned char sunflowers5[][153600];//18帧
extern const unsigned char sunflowers[][153600];//36帧
#define LCD_XSIZE LCD_WIDTH
#define LCD_YSIZE LCD_HEIGHT
#define SCR_XSIZE LCD_WIDTH
#define SCR_YSIZE LCD_HEIGHT


volatile static unsigned short LCD_BUFFER[SCR_YSIZE][SCR_XSIZE];

/**************************************************************
640×480 TFT LCD数据和控制端口初始化
**************************************************************/
static void Lcd_Port_Init( void )
{
rGPCUP=0xffffffff; // Disable Pull-up register
rGPCCON=0xaaaa02a8; //Initialize VD[7:0],VM,VFRAME,VLINE,VCLK

rGPDUP=0xffffffff; // Disable Pull-up register
rGPDCON=0xaaaaaaaa; //Initialize VD[15:8]
}

/**************************************************************
640×480 TFT LCD功能模块初始化
**************************************************************/
static void LCD_Init(void)
{
#defineM5D(n)((n)&0x1fffff)
#define LCD_ADDR ((U32)LCD_BUFFER)
rLCDCON1 = (LCD_PIXCLOCK << 8) | (3 << 5) | (12 << 1);
rLCDCON2 = (LCD_UPPER_MARGIN << 24) | ((LCD_HEIGHT - 1) << 14) | (LCD_LOWER_MARGIN << 6) | (LCD_VSYNC_LEN << 0);
rLCDCON3 = (LCD_RIGHT_MARGIN << 19) | ((LCD_WIDTH - 1) << 8) | (LCD_LEFT_MARGIN << 0);
rLCDCON4 = (13 << 8) | (LCD_HSYNC_LEN << 0);

#if !defined(LCD_CON5)
# define LCD_CON5 ((1<<11) | (1 << 9) | (1 << 8) | (1 << 3) | (1 << 0))
#endif
rLCDCON5 = LCD_CON5;

rLCDSADDR1 = ((LCD_ADDR >> 22) << 21) | ((M5D(LCD_ADDR >> 1)) << 0);
rLCDSADDR2 = M5D((LCD_ADDR + LCD_WIDTH * LCD_HEIGHT * 2) >> 1);
rLCDSADDR3 = LCD_WIDTH;

rLCDINTMSK |= 3;
rTCONSEL &= (~7);


rTPAL = 0x0;
rTCONSEL &= ~((1<<4) | 1);


}

/**************************************************************
LCD视频和控制信号输出或者停止,1开启视频输出
**************************************************************/
static void Lcd_EnvidOnOff(int onoff)
{
if(onoff==1)
rLCDCON1|=1; // ENVID=ON
else
rLCDCON1 =rLCDCON1 & 0x3fffe; // ENVID Off
}

/**************************************************************
320×240 8Bpp TFT LCD 电源控制引脚使能
**************************************************************/
static void Lcd_PowerEnable(int invpwren,int pwren)
{
//GPG4 is setted as LCD_PWREN
rGPGUP = rGPGUP|(1<<4); // Pull-up disable
rGPGCON = rGPGCON|(3<<8); //GPG4=LCD_PWREN

//Enable LCD POWER ENABLE Function
rLCDCON5 = rLCDCON5&(~(1<<3))|(pwren<<3); // PWREN
rLCDCON5 = rLCDCON5&(~(1<<5))|(invpwren<<5); // INVPWREN
}


/**************************************************************
640×480 TFT LCD单个象素的显示数据输出
**************************************************************/
static void PutPixel(U32 x,U32 y,U16 c)
{
if(x<SCR_XSIZE && y<SCR_YSIZE)
LCD_BUFFER[(y)][(x)] = c;
}

/**************************************************************
640×480 TFT LCD全屏填充特定颜色单元或清屏
**************************************************************/
static void Lcd_ClearScr( U16 c)
{
unsigned int x,y ;

for( y = 0 ; y < SCR_YSIZE ; y++ )
{
for( x = 0 ; x < SCR_XSIZE ; x++ )
{
LCD_BUFFER[y][x] = c ;
}
}
}

/**************************************************************
LCD屏幕显示垂直翻转
// LCD display is flipped vertically
// But, think the algorithm by mathematics point.
// 3I2
// 4 I 1
// --+-- <-8 octants mathematical cordinate
// 5 I 8
// 6I7
**************************************************************/
static void Glib_Line(int x1,int y1,int x2,int y2, U16 color)
{
int dx,dy,e;
dx=x2-x1;
dy=y2-y1;

if(dx>=0)
{
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 1/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else// 2/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)

if(dx>=dy) // 8/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else// 7/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
else //dx<0
{
dx=-dx;//dx=abs(dx)
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 4/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else// 3/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else // dy<0
{
dy=-dy; // dy=abs(dy)

if(dx>=dy) // 5/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
PutPixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else// 6/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
PutPixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
}


/**************************************************************
在LCD屏幕上用颜色填充一个矩形
**************************************************************/
static void Glib_FilledRectangle(int x1,int y1,int x2,int y2, U16 color)
{
int i;

for(i=y1;i<=y2;i++)
Glib_Line(x1,i,x2,i,color);
}

/**************************************************************
在LCD屏幕上指定坐标点画一个指定大小的图片
**************************************************************/
static void Paint_Bmp(int x0,int y0,int h,int l,const unsigned char *bmp)
{
int x,y;
U32 c;
int p = 0;

for( y = 0 ; y < l ; y++ )
{
for( x = 0 ; x < h ; x++ )
{
c = bmp[p+1] | (bmp[p]<<8) ;

if ( ( (x0+x) < SCR_XSIZE) && ( (y0+y) < SCR_YSIZE) )
LCD_BUFFER[y0+y][x0+x] = c ;

p = p + 2 ;
}
}
}

/**************************************************************
**************************************************************/
void TFT_LCD_Init(void)
{
//int t;

LCD_Init();
LcdBkLtSet( 70 ) ;
Lcd_PowerEnable(0, 1);
Lcd_EnvidOnOff(1);//turn on vedio

Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );

#if defined(LCD_N35) || defined(LCD_T35) || defined(LCD_X35)
Paint_Bmp(0, 0, 240, 320, sunflower_240x320);
#elif defined(LCD_A70)
Paint_Bmp(0, 0, 800, 480, sunflower_800x480);
#elif defined(LCD_L80)
Paint_Bmp(0, 0, 640, 480, sunflower_640x480);
#elif defined(LCD_VGA1024768)
Paint_Bmp(0, 0, 1024, 768, sunflower_1024x768);
#elif defined(LCD_W35)
Paint_Bmp(0, 0, 320, 240, sunflower_320x240);

#endif


//#define MY_DELAY 76800
//t=MY_DELAY;
// while (t--){;}
//Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );
}

/**************************************************************
**************************************************************/
void TFT_LCD_Test(void)
{
int i;
int t;
#define FRAMENUM 18
//视频转换的数组实在是太大了、每个.c文件都十几兆大小、打开好卡、修改起来好卡、保存好卡、卡得人撞卡车的心都被卡住了。因此对文件做了切分
//诶、60.5兆的文件才放了5秒的视频,**都碎了啊,本想把整个视频3分39秒全放进去的说、经过反反复复反反复复检测、18帧/s的视频放六秒的话就会
//花屏(原因是内存不够了,从0x30000000开始放,要放6秒早就超0x40000000了)
#define MY_DELAY 153600 //该处的延迟是我随便设的、勉强差不多速度看似好像大概可能和原视频一样吧
t=MY_DELAY;
while (t--){;}
while(1)
{
for(i=0;i<FRAMENUM*2;i++)
{
// Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );
Paint_Bmp(0, 0, 320, 240, sunflowers[i]);
t=MY_DELAY;
while (t--){;}
}


for(i=0;i<FRAMENUM;i++)
{
// Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );
Paint_Bmp(0, 0, 320, 240, sunflowers3[i]);
t=MY_DELAY;
while (t--){;}
}
for(i=0;i<FRAMENUM;i++)
{
// Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );
Paint_Bmp(0, 0, 320, 240, sunflowers4[i]);
t=MY_DELAY;
while (t--){;}
}
for(i=0;i<FRAMENUM;i++)
{
// Lcd_ClearScr( (0x00<<11) | (0x00<<5) | (0x00) );
Paint_Bmp(0, 0, 320, 240, sunflowers5[i]);
t=MY_DELAY;
while (t--){;}
}
}
//Lcd_EnvidOnOff(0);//turn off vedio
}
//*************************************************************

视频文件的格式跟图片数组的格式类似,只不过维数多了一维(时间)而已。我生成视频数组的方法是先把视频转为avi的格式,然后用Matlab来转换,实在是太**了。

Matlab程序如下:

function convent(avi)
avi='Bad Apple 0~12.avi'
img=aviread(char(avi))

t =size(img,2)
a=size(img(1,1).cdata,1);
b=size(img(1,1).cdata,2);
c=size(img(1,1).cdata,3);

fid=fopen('e:\sg.txt','wt');
fprintf(fid,'const unsigned char sunflowers4[][153600] = {\n');
%t=1
for k=1:1:t
fprintf(fid,'//%d\n{',k);
for i=1:1:240
for j=1:1:40
for m=(8*j-7):1:(8*j)
fprintf(fid,'0x%x,', bitor(bitand(img(1,k).cdata(i,m,1),248),bitshift(img(1,k).cdata(i,m,2),-5)));
fprintf(fid,'0x%x,', bitshift(bitand(img(1,k).cdata(i,m,2),28),3)+bitshift(img(1,k).cdata(i,m,3),-3));
end
fprintf(fid,'\n');
end
fprintf(fid,'\n\n\n');
% z=i
end
fprintf(fid,'},');
u=k
end
fprintf(fid,'};');
fclose(fid)

end
不建议转换超过5秒的视频,截取219帧(注:≈12秒、每秒18帧)的《bad apple》我就转换了一个多小时!!!看样子要想想有没有其他办法了。这实在是太*****了。

以下为结果图:

让mini2440播放视频(简易版)

注:视频原本就是黑白的:来源于著名PV 影绘视频 Bad Apple

之所以选这个视频,是因为黑白的做压缩效率应该很高,不过这是续篇的事了。