#include #include #include #include #include #include #include #include #include #define W 720 #define H 576 static unsigned char frame[720*576*3/2]; static unsigned char framey[W*H]; static unsigned char frameu[W*H / 4]; static unsigned char framev[W*H / 4]; static unsigned int osd[720*576]; static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h) { unsigned int y, x, i; // descramble Y plane // dstride = 720 = w // The Y plane is divided into blocks of 16x16 pixels // Each block in transmitted in turn, line-by-line. for (y = 0; y < h; y += 16) { for (x = 0; x < w; x += 16) { for (i = 0; i < 16; i++) { memcpy(dst + x + (y + i) * dstride, src, 16); src += 16; } } } } static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h) { unsigned int y, x, i; // descramble U/V plane // dstride = 720 / 2 = w // The U/V values are interlaced (UVUV...). // Again, the UV plane is divided into blocks of 16x16 UV values. // Each block in transmitted in turn, line-by-line. for (y = 0; y < h; y += 16) { for (x = 0; x < w; x += 8) { for (i = 0; i < 16; i++) { int idx = x + (y + i) * dstride; dstu[idx+0] = src[0]; dstv[idx+0] = src[1]; dstu[idx+1] = src[2]; dstv[idx+1] = src[3]; dstu[idx+2] = src[4]; dstv[idx+2] = src[5]; dstu[idx+3] = src[6]; dstv[idx+3] = src[7]; dstu[idx+4] = src[8]; dstv[idx+4] = src[9]; dstu[idx+5] = src[10]; dstv[idx+5] = src[11]; dstu[idx+6] = src[12]; dstv[idx+6] = src[13]; dstu[idx+7] = src[14]; dstv[idx+7] = src[15]; src += 16; } } } } /*************************************************************************/ int main(int argc, char **argv) { char *device = "/dev/fb0"; FILE *fin; int fd; int x, y; struct ivtvfb_dma_frame df; struct fb_var_screeninfo vi; if (argc > 1) device = argv[1]; fin = stdin; fd = open(device, O_RDWR); if (fd == -1) { fprintf(stderr, "cannot open %s\n", device); exit(-1); } ioctl(fd, FBIOGET_VSCREENINFO, &vi); vi.nonstd = 1; vi.bits_per_pixel = 32; vi.xres = W; vi.yres = H; vi.xres_virtual = W; vi.yres_virtual = H; vi.xoffset = 0; vi.yoffset = 0; ioctl(fd, FBIOPUT_VSCREENINFO, &vi); while (fread(frame, 1, sizeof(frame), fin)) { de_macro_y(framey, frame, W, W, H); de_macro_uv(frameu, framev, frame + 720 * H, W / 2, W / 2, H / 2); for (y = 0; y < H; y++) { for (x = 0; x < W; x++) { int y2 = y*2; int x2 = x * 2; if (x < W / 2 && y < H / 2) osd[y * W + x] = (framey[y2 * W + x2] << 16) | (frameu[(y2/2) * (W/2) + x2/2] << 8) | (framev[(y2/2) * (W/2) + x2/2]) | 0x8f000000; else osd[y * W + x] = 0x00000000; } } df.source = osd; df.dest_offset = 0; df.count = sizeof(osd); ioctl(fd, IVTVFB_IOC_DMA_FRAME, &df); } fclose(fin); return 0; }