#include #include #include #include #include #include #include #include #if defined(__linux__) #include #elif defined(__FreeBSD__) #include #endif #include "display.h" short rdata[SCC_NTSCWIDTH * SCC_NTSCHEIGHT]; unsigned char rgbdata[SCC_NTSCWIDTH * SCC_NTSCHEIGHT * 4]; unsigned char yuvdata[SCC_NTSCWIDTH * SCC_NTSCHEIGHT * 2]; unsigned char *pdata; int hwidth = SCC_NTSCWIDTH / 2; int hheight = SCC_NTSCHEIGHT; int format = 0; struct scc_geomet scc; struct scc_tv scc_tv; int verbose; int spd_mode = SCC_FAST; #ifdef SH_MEM int shmem = 1; #else int shmem = 0; #endif int dithertype = -1; int loop = 0; double r0, r1, r2, r3, r4, r5; double interval = 30; int ff; int vsize; int nframes = -1; int sccat = 0; int tvchannel, tv; double gettime() { struct timeval a; gettimeofday(&a, NULL); return((double)(a.tv_sec + a.tv_usec * 1E-6)); } void xdisp(double a,double c) { double b; b = gettime(); r1 += b - a; if (dithertype == ORDERED_DITHER) OrderedDitherImage(yuvdata, yuvdata + vsize, yuvdata + vsize + vsize / 4, pdata, hheight, hwidth); a = gettime(); r2 += a - b; ExecuteDisplay(); b = gettime(); r3 += b - a; { double t = interval - (b-c)*1e6; if(t >0) usleep(t); } a = gettime(); r4 += a - b; r5 += a - c; if (verbose) { ff++; if (ff == 100) { printf("read %8.3f\n", r0 / ff); printf("raw -> xxx %8.3f\n", r1 / ff); printf("xxx -> Ximage %8.3f\n", r2 / ff); printf("Draw %8.3f\n", r3 / ff); printf("Idle %8.3f\n", r4 / ff); printf("Total(FPS) %8.3f (%8.3f) \n\n", r5/ff,ff/r5); ff = 0; r0 = 0; r1 = 0; r2 = 0; r3 = 0; r4 = 0; r5 = 0; } } } rgb565_depth16(int video) { double c, b; int size; size = vsize * sizeof(short); while((nframes < 0) || ++loop < nframes){ c = gettime(); lseek(video, 0, SEEK_SET); read(video, pdata, size); b = gettime(); r0 += b - c; xdisp(b, c); } } rgb565_fullcolor(int video) { double c, b; int i, j, n, size; size = vsize * sizeof(short); while((nframes < 0) || ++loop < nframes){ c = gettime(); n = 0; lseek(video, 0, SEEK_SET); read(video, rdata, size); b = gettime(); r0 += b - c; for (i = 0; i < hheight; i++){ for (j = 0; j < hwidth; j++) { pdata[n++] = (unsigned char) ((rdata[i * hwidth + j] & 0x001f) << 3); pdata[n++] = (unsigned char) ((rdata[i * hwidth + j] & 0x07e0) >> 3); pdata[n++] = (unsigned char) ((rdata[i * hwidth + j] & 0xf800) >> 8); n++; } } xdisp(b, c); } } yuv422_ordered(int video) { double c, b; int size; unsigned char *y, *u, *v; int i, j, yy, uv; size = vsize * sizeof(short); while((nframes < 0) || ++loop < nframes){ c = gettime(); lseek(video, 0, SEEK_SET); read(video, rdata, size); b = gettime(); r0 += b - c; yy = 0; uv = 0; y = yuvdata; u = y + vsize; v = u + vsize / 4; for (i = 0; i < hheight; i++){ for (j = 0; j < hwidth;) { if (!(i % 2)) { y[yy++] = (unsigned char) ((rdata[i * hwidth + j] & 0xff00) >> 8); u[uv] = (unsigned char) ((rdata[i * hwidth + j] & 0x00ff) ^ 0x80); j++; y[yy++] = (unsigned char) ((rdata[i * hwidth + j] & 0xff00) >> 8); v[uv] = (unsigned char) ((rdata[i * hwidth + j] & 0x00ff) ^ 0x80); uv++; j++; } else { y[yy++] = (unsigned char) ((rdata[i * hwidth + j] & 0xff00) >> 8); j++; } } } xdisp(b, c); } } yuv422_gray(int video) { double c, b; int size; unsigned char *y, *u, *v; int i, j, yy, uv; size = vsize * sizeof(short); while((nframes < 0) || ++loop < nframes){ c = gettime(); lseek(video, 0, SEEK_SET); read(video, rdata, size); b = gettime(); r0 += b - c; yy = 0; uv = 0; y = yuvdata; u = y + vsize; v = u + vsize / 4; for (i = 0; i < hheight; i++){ for (j = 0; j < hwidth;j++) { pdata[i * hwidth + j] = pixel[(unsigned char) ((rdata[i * hwidth + j] & 0xff00) >> 8)]; } } xdisp(b, c); } } main(int narg, char **argv) { int video; int oarg; extern char *optarg; while ((oarg = getopt(narg, argv, "x:y:vhsSgn:ci:t:")) > 0) { switch (oarg) { case 'x': hwidth = atoi(optarg); break; case 'y': hheight = atoi(optarg); break; case 'v': verbose = 1; break; case 'S': spd_mode = 1; break; case 'h': printf("Usage:\n"); printf(" %s [options]\n", argv[0]); printf(" Options:\n"); printf(" -x width Set width\n"); printf(" -y height Set height\n"); printf(" -s No Shared Memory \n"); printf(" -S Slow Mode \n"); printf(" -g Grayscale (Only 8bit Display) \n"); printf(" -n frames Set frames\n"); printf(" -i msec Set Interval\n"); printf(" -c stdout by 24bit ppm\n"); printf(" -t channel Set TV Channel\n"); printf(" -v Verbose Output\n"); printf(" -h Help\n"); exit(0); break; case 's': shmem = 0; break; case 'g': dithertype = GRAY_DITHER; break; case 'i': interval = atoi(optarg); break; case 'n': nframes = atoi(optarg); break; case 'c': sccat = 1; break; case 't': tv=1; tvchannel = atoi(optarg); break; default: fprintf(stderr, "%s : Unknown option or error " "in option\n", argv[0]); exit(1); } } hwidth = (int) (hwidth / 8) * 8; hheight = (int) (hheight / 4) * 4; video = open("/dev/scc0", O_RDONLY); if (video < 0) { fprintf(stderr, "open failed: %s\n", strerror(errno)); exit(1); } scc.width = hwidth; scc.height = hheight; if (ioctl(video, SCCSETGEO, &scc)) { perror("ioctl"); exit(1); } if(tv){ scc_tv.tuntype = 0x61; scc_tv.channel = tvchannel; scc_tv.fine = 0; scc_tv.country = 0; if (ioctl(video, SCCSETTVCHANNEL, &scc_tv)) { perror("ioctl"); exit(1); } } if(sccat){ int i,j,n = 0; spd_mode = SCC_SLOW; if (ioctl(video, SCCSETSPDMODE, &spd_mode)) { perror("ioctl"); exit(1); } sleep(1); /* ad hot! but necessary */ printf("P6\n"); printf("%d %d\n",hwidth,hheight); printf("255\n"); fflush(stdout); read(video,rdata,hwidth*hheight*sizeof(short)); close(video); for(i=0;i> 8); rgbdata[n++]=(char)((rdata[i*hwidth+j]&0x07e0) >> 3); rgbdata[n++]=(char)((rdata[i*hwidth+j]&0x001f) << 3); } write(fileno(stdout),rgbdata,hwidth*hheight*3); exit(0); } interval = interval * 1000; vsize = hwidth * hheight; MakeWindow(NULL); switch (depth) { case 8: if (dithertype != GRAY_DITHER) { dithertype = ORDERED_DITHER; InitColor(); InitOrderedDither(); } format = SCC_YUV422; break; case 16: if (dithertype != GRAY_DITHER) { dithertype = DEPTH16; format = SCC_RGB565; } else { fprintf(stderr, "xscc can not display Grayscale on %d bit display.\n", depth); exit(1); } break; case 24: case 32: if (dithertype != GRAY_DITHER) { dithertype = FULL_COLOR_DITHER; format = SCC_RGB565; } else { fprintf(stderr, "xscc can not display Grayscale on %d bit display.\n", depth); exit(1); } break; default: fprintf(stderr, "xscc can not display.\n"); exit(1); } InitDisplay(); if (ioctl(video, SCCSETFMT, &format)) { perror("ioctl"); exit(1); } if (ioctl(video, SCCSETSPDMODE, &spd_mode)) { perror("ioctl"); exit(1); } switch(format){ case SCC_RGB565: switch (dithertype) { case DEPTH16: rgb565_depth16(video); break; case FULL_COLOR_DITHER: rgb565_fullcolor(video); break; } break; case SCC_YUV422: switch (dithertype) { case ORDERED_DITHER: yuv422_ordered(video); break; case GRAY_DITHER: yuv422_gray(video); break; } break; default: fprintf(stderr, "bad format\n"); } close(video); }