#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>
char *fb_addr;
unsigned fb_size;
static void copy16(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, int mm, int nn)
{
p_linear_addr[mm] = p_tiled_addr[nn];
p_linear_addr[mm + 1] = p_tiled_addr[nn+ 1];
p_linear_addr[mm + 2] = p_tiled_addr[nn+ 2];
p_linear_addr[mm + 3] = p_tiled_addr[nn+ 3];
p_linear_addr[mm + 4] = p_tiled_addr[nn+ 4];
p_linear_addr[mm + 5] = p_tiled_addr[nn+ 5];
p_linear_addr[mm + 6] = p_tiled_addr[nn+ 6];
p_linear_addr[mm + 7] = p_tiled_addr[nn+ 7];
p_linear_addr[mm + 8] = p_tiled_addr[nn+ 8];
p_linear_addr[mm + 9] = p_tiled_addr[nn+ 9];
p_linear_addr[mm + 10] = p_tiled_addr[nn+ 10];
p_linear_addr[mm + 11] = p_tiled_addr[nn+ 11];
p_linear_addr[mm + 12] = p_tiled_addr[nn+ 12];
p_linear_addr[mm + 13] = p_tiled_addr[nn+ 13];
p_linear_addr[mm + 14] = p_tiled_addr[nn+ 14];
p_linear_addr[mm + 15] = p_tiled_addr[nn+ 15];
}
static int tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos)
{
int pixel_x_m1, pixel_y_m1;
int roundup_x, roundup_y;
int linear_addr0, linear_addr1, bank_addr ;
int x_addr;
int trans_addr;
pixel_x_m1 = x_size -1;
pixel_y_m1 = y_size -1;
roundup_x = ((pixel_x_m1 >> 7) + 1);
roundup_y = ((pixel_x_m1 >> 6) + 1);
x_addr = (x_pos >> 2);
if ((y_size <= y_pos+32) && ( y_pos < y_size) &&
(((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0))
{
linear_addr0 = (((y_pos & 0x1f) <<4) | (x_addr & 0xf));
linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f));
if(((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
bank_addr = ((x_addr >> 4) & 0x1);
else
bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
}
else
{
linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf));
linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f));
if(((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1))
bank_addr = ((x_addr >> 4) & 0x1);
else
bank_addr = 0x2 | ((x_addr >> 4) & 0x1);
}
linear_addr0 = linear_addr0 << 2;
trans_addr = (linear_addr1 <<13) | (bank_addr << 11) | linear_addr0;
return trans_addr;
}
static void tile_to_linear_4x2(unsigned char *p_linear_addr, unsigned char *p_tiled_addr, unsigned int x_size, unsigned int y_size)
{
int trans_addr;
unsigned int i, j, k, nn, mm, index;
// .. TILE 4x2 test
for (i = 0; i < y_size; i = i + 16)
{
for (j = 0; j < x_size; j = j + 16)
{
trans_addr = tile_4x2_read(x_size, y_size, j, i);
index = i*x_size + j;
k = 0; nn = trans_addr + (k << 6); mm = index;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 1; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 2; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 3; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 4; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 5; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 6; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 7; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 8; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 9; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 10; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 11; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 12; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 13; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 14; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
k = 15; nn = trans_addr + (k << 6); mm += x_size;
copy16(p_linear_addr, p_tiled_addr, mm, nn);
}
}
}
int convert_yuv_to_rgb_pixel(int y, int u, int v)
{
unsigned int pixel32 = 0;
unsigned char *pixel = (unsigned char *)&pixel32;
int r, g, b;
/*
r = y + (1.4075 * (v-128));
g = y - (0.3455 * (u-128)) - (0.7169 * (v-128));
b = y + (1.7790 * (u-128));
*/
/*
r = y + v + v >> 2 + v >> 3 + v >> 5;
g = y - (u >> 2 + u >> 4 + u >> 5) - (v >> 1 + v >> 3 + v >> 4 + v >> 5);
b = y + u + u >> 1 + u >> 2 + u >> 6;
*/
/*
r = y + 1.13983 * v;
g = y - 0.39465 * u - 0.58060 * v;
b = y + 2.03211 *u;
*/
r = 1.164 * (y - 16) + 1.596 * (v - 128);
g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.392 * (u - 128);
b = 1.164 * (y - 16) + 2.017 * (u - 128);
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
pixel[0] = r * 220 / 256;
pixel[1] = g * 220 / 256;
pixel[2] = b * 220 / 256;
pixel[3] = 0;
// printf("%s\n", __FUNCTION__);
// pixel32 = 0 | (r << 16) | (g << 8) | b;
return pixel32;
}
int convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned int *rgb, unsigned int width, unsigned int height)
{
unsigned int pixel_in;
unsigned int in, out = 0;
int y0, y1, y2, y3, u, v;
for(in = 0; in < 640*480; in += 4)
{
y0 = yuv[in + 0];
y1 = yuv[in + 1];
y2 = yuv[in + 2];
y3 = yuv[in + 3];
//v = yuv[in + 40960];
//u = yuv[in + 40960 + 1];
v = u = 128;
rgb[out++] = convert_yuv_to_rgb_pixel(y0, u, v);
rgb[out++] = convert_yuv_to_rgb_pixel(y1, u, v);
rgb[out++] = convert_yuv_to_rgb_pixel(y2, u, v);
rgb[out++] = convert_yuv_to_rgb_pixel(y3, u, v);
// printf("out = %d, rgb[out] = %x\n", out, rgb[out]);
}
/* unsigned int pixel_in;
unsigned int in, out = 0;
int y00, y01, y02, y03, y10, y11, y12, y13, u0, v0, u1, v1;
for(in = 0; in < 640*480; in += 8)
{
y00 = yuv[in + 0];
y01 = yuv[in + 1];
y02 = yuv[in + 2];
y03 = yuv[in + 3];
y10 = yuv[in + 4];
y11 = yuv[in + 5];
y12 = yuv[in + 6];
y13 = yuv[in + 7];
// v0 = yuv[in + 40960];
// u0 = yuv[in + 40960 + 1];
// v1 = yuv[in + 40960 + 2];
// u1 = yuv[in + 40960 + 3];
v0 = u0 = v1 = u1 = 0;
rgb[out++] = convert_yuv_to_rgb_pixel(y00, u0, v0);
rgb[out++] = convert_yuv_to_rgb_pixel(y01, u0, v0);
rgb[out++] = convert_yuv_to_rgb_pixel(y02, u1, v1);
rgb[out++] = convert_yuv_to_rgb_pixel(y03, u1, v1);
rgb[out++] = convert_yuv_to_rgb_pixel(y10, u0, v0);
rgb[out++] = convert_yuv_to_rgb_pixel(y11, u0, v0);
rgb[out++] = convert_yuv_to_rgb_pixel(y12, u1, v1);
rgb[out++] = convert_yuv_to_rgb_pixel(y13, u1, v1);
// printf("out = %d, rgb[out] = %x\n", out, rgb[out]);
}*/
return 0;
}
int print_screen(int *buf,int width,int height);
int main(int argc,char *argv[])
{
int screen_fbd=0;
struct fb_fix_screeninfo fb_fix;
struct fb_var_screeninfo fb_var;
char *env=NULL;
env="/dev/fb0";
screen_fbd=open(env,O_RDWR);
printf("Success opening framebuffer device %s\n",env);
ioctl(screen_fbd,FBIOGET_FSCREENINFO,&fb_fix);
printf("fb_fix.line_length=%d\n",fb_fix.line_length);
printf("fb_fix.accel=%d\n",fb_fix.accel);
ioctl(screen_fbd,FBIOGET_VSCREENINFO,&fb_var);
printf("fb_var.xres=%d\n",fb_var.xres);
printf("fb_var.yres=%d\n",fb_var.yres);
fb_size=fb_var.yres*fb_fix.line_length;
fb_addr=(char *)mmap(NULL,fb_size,PROT_READ|PROT_WRITE,MAP_SHARED,screen_fbd,0);
/*以上为打印终端信息*/
FILE *in;
unsigned char *yuv;
unsigned int *rgb;
unsigned char *yuv_nv12;
in = fopen(argv[1], "rb");
if(!in)
return 1;
yuv = (unsigned char *)malloc(307200); /*此数据有空白处 实际为640*480*1.5 = 460800, 524288 = 0x80000 = 0x5000 + 0x30000*/
if(yuv == NULL)
return -1;
fread(yuv, 307200, 1, in);
fclose(in); //读取数据到buffer
yuv_nv12 = (unsigned cha