int init_framebuffer() { struct fb_var_screeninfo vinfo; int fb = -1; struct fbinfo fbinfo; unsigned i, bytespp; //int w,h,f; //void const* base = 0; //size_t size = 0; int iversion = get_android_version(); int busefb = 1; if( !g_forcefbmode && iversion >= 10 /* ICE_CREAM_SANDWICH */) { uint32_t w=0, h=0; PixelFormat fmt=0; int chk = 0; ScreenshotClient sc; //const String16 name("SurfaceFlinger"); //sp<ISurfaceComposer> composer; //getService(name, &composer); //sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(0); //sp<IBinder> display(composer->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); //sp<IBinder> display = composer->getBuiltInDisplay(id); //sc.update(display); sc.update(); w = sc.getWidth(); h = sc.getHeight(); fmt = sc.getFormat(); sc.release(); /* sp<IMemoryHeap> heap; sp<ISurfaceComposer> sf(ComposerService::getComposerService()); sf->captureScreen(0, &heap, &w, &h, &fmt, 0, 0, 0, 0x7fffffff); */ Log("fmt(%d), w(%d), h(%d)\n", fmt, w, h); if( set_fbinfo(fmt,w,h, &fbinfo) != 0 ) busefb = 0; } if( busefb ) { // not support screencap fb = open("/dev/graphics/fb0", O_RDONLY); if(fb < 0) { Err("Error:fb open error.\n"); return 0; } if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) return 0; fcntl(fb, F_SETFD, FD_CLOEXEC); bytespp = vinfo.bits_per_pixel / 8; fbinfo.version = BEFORE_ICS; fbinfo.bpp = vinfo.bits_per_pixel; fbinfo.size = vinfo.xres * vinfo.yres * bytespp; fbinfo.width = vinfo.xres; fbinfo.height = vinfo.yres; fbinfo.red_offset = vinfo.red.offset; if( vinfo.red.msb_right !=0) { Log("red MSB is on right\n"); fbinfo.red_offset = vinfo.bits_per_pixel - vinfo.red.offset - vinfo.red.length; } fbinfo.red_length = vinfo.red.length; fbinfo.red_mask = getMask(vinfo.red.length); fbinfo.green_offset = vinfo.green.offset; if( vinfo.green.msb_right != 0) { Log("green MSB is on right\n"); fbinfo.green_offset = vinfo.bits_per_pixel - vinfo.green.offset - vinfo.green.length; } fbinfo.green_length = vinfo.green.length; fbinfo.green_mask = getMask(vinfo.green.length); fbinfo.blue_offset = vinfo.blue.offset; if( vinfo.blue.msb_right != 0) { Log("blue MSB is on right\n"); fbinfo.blue_offset = vinfo.bits_per_pixel - vinfo.blue.offset - vinfo.blue.length; } fbinfo.blue_length = vinfo.blue.length; fbinfo.blue_mask = getMask(vinfo.blue.length); fbinfo.alpha_offset = vinfo.transp.offset; fbinfo.alpha_length = vinfo.transp.length; fbinfo.alpha_mask = getMask(vinfo.transp.length); close(fb); } fbinfo.orientation = 0; //get_dev_rotation(); memcpy(&g_fbinfo, &fbinfo, sizeof(struct fbinfo)); g_fbbuffer = (unsigned char*)malloc( fbinfo.width * fbinfo.height * 32/8); g_xsize = fbinfo.width * fbinfo.bpp / 8; g_x = (unsigned char*)malloc( fbinfo.width * 4); jpegBufSize = fbinfo.width * fbinfo.height * 32/8 * 2 / 3; fbc_output[0].jpegBuf = (char*)malloc( jpegBufSize ); #ifdef USE_XOR_MODE fbc_output[1].jpegBuf = (char*)malloc( jpegBufSize ); memset(fbc_output[1].jpegBuf , 0, jpegBufSize); #endif fbc_output_current = 0; int isBigEndian = is_big_endian(); Log("xres=%d, yres=%d, bpp=%d red(off:%d,len:%d), green(%d,%d), blue(%d,%d)\n\ isBigEndian(%d), half(%d), forcefb(%d)\n", (int)fbinfo.width, (int)fbinfo.height, (int)fbinfo.bpp, (int) fbinfo.red_offset, (int)fbinfo.red_length, (int) fbinfo.green_offset, (int)fbinfo.green_length, (int) fbinfo.blue_offset, (int)fbinfo.blue_length, isBigEndian, g_halfmode, g_forcefbmode ); if( fbinfo.version == ICS_SCREENCAP) Log("Capturing Method : ICS_SCREENCAP\n"); else Log("Capturing Method : FB_ACCESS\n"); int tresult = detect_touch_port(0); Log("Detect touch port : %d\n", tresult); return 1; }
int read_rgb_framebuffer_screencap_to_jpeg(svcInfoPtr psvc) { #ifdef PERFORMANCE_REPORT struct timeval tS, tE; gettimeofday(&tS,NULL); #endif void const* mapbase = 0; size_t size = 0; int nRtn; /* if (pscreenshot->update() == NO_ERROR) { mapbase = pscreenshot->getPixels(); //w = pscreenshot->getWidth(); //h = pscreenshot->getHeight(); //f = pscreenshot->getFormat(); size = pscreenshot->getSize(); } else { Err("Error:ScreenshotClient init failed.\n"); return 0; }*/ unsigned int sw, sh, xsize, gsize; sw = g_fbinfo.width; sh = g_fbinfo.height; xsize = g_xsize; gsize = g_fbinfo.size; if( g_halfmode) { sw /= 2; sh /= 2; xsize /= 2; gsize /= 4; } uint32_t w=0, h=0; PixelFormat fmt=0; //Log("w(%d) h(%d) sw(%d) sh(%d) xsize(%d) gsize(%d)\n", w, h, sw, sh, xsize, gsize); ScreenshotClient sc; sc.update(sw,sh); /* sp<IMemoryHeap> heap; sp<ISurfaceComposer> sf(ComposerService::getComposerService()); sf->captureScreen(0, &heap, &w, &h, &fmt, sw, sh, 0, 0x7fffffff); mapbase = heap->getBase(); */ mapbase = sc.getPixels(); //Log("w(%d) h(%d) sw(%d) sh(%d) xsize(%d) gsize(%d)\n", w, h, sw, sh, xsize, gsize); if( mapbase != NULL) { unsigned char* base = (unsigned char*)((char const *)mapbase); unsigned char* p = g_fbbuffer; unsigned int i,j; #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_capture += ELAPSED(tS, tE); tS = tE; #endif init_jpeg(psvc->jpegquality); #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_compress += ELAPSED(tS, tE); tS = tE; #endif for(i=0; i< gsize; i += xsize) { #ifdef USE_XOR_MODE for(unsigned int t=0; t< xsize; t++) { *(g_x + t) = (*(fbc_output[1].jpegBuf + i + t) ^ *(base + t)); } #else memcpy(g_x, base, xsize); #endif #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_capture += ELAPSED(tS, tE); tS = tE; #endif nRtn = convert_to_rgb(g_x, xsize, p); #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_colorspace += ELAPSED(tS, tE); tS = tE; #endif rowPointer[0] = p; jpeg_write_scanlines(&cinfo, rowPointer, 1); p += nRtn; #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_compress += ELAPSED(tS, tE); tS = tE; #endif base += xsize; } if( gsize % xsize > 0 ) { memcpy(g_x, base, gsize % xsize ); #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_capture += ELAPSED(tS, tE); tS = tE; #endif nRtn = convert_to_rgb(g_x, xsize, p); #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_colorspace += ELAPSED(tS, tE); tS = tE; #endif rowPointer[0] = p; jpeg_write_scanlines(&cinfo, rowPointer, 1); p += nRtn; #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_compress += ELAPSED(tS, tE); tS = tE; #endif } #ifdef USE_XOR_MODE memcpy(fbc_output[1].jpegBuf , (unsigned char*)((char const *)mapbase), gsize); #endif int nSize = exit_jpeg(); // release sc sc.release(); //Log("jpeg size:%d - ", nSize); if( nSize > 0 ) { //FBCCMD res; fbc_output[fbc_output_current].cmd = g_halfmode ? 'h' : 'u'; fbc_output[fbc_output_current].size = htonl(FBCCMD_HEADER + nSize); LOCK(psvc->output_mutex); int r1,r2; r1 = WriteExact(psvc, (const char*)&fbc_output[fbc_output_current], FBCCMD_HEADER); // actual data //char * test = (char*)&fbc_output[fbc_output_current]; r2 = WriteExact(psvc, fbc_output[fbc_output_current].jpegBuf, nSize); //Log("W1:%d W2:%d (%02x %02x %02x %02x %02x %02x %02x %02x\n", r1, r2, // test[0], test[1], test[2], test[3], test[4], test[5], test[6], test[7] ); UNLOCK(psvc->output_mutex); } #ifdef PERFORMANCE_REPORT gettimeofday(&tE,NULL); psvc->frame_tx += ELAPSED(tS, tE); tS = tE; #endif return nSize; } else { Err("map failed!!!\n"); } return 0; }
int main(int argc, char** argv) { const char* pname = argv[0]; bool png = false; int c; while ((c = getopt(argc, argv, "ph")) != -1) { switch (c) { case 'p': png = true; break; case '?': case 'h': usage(pname); return 1; } } argc -= optind; argv += optind; int fd = -1; /* if (argc == 0) { fd = dup(STDOUT_FILENO); } else if (argc == 1) { const char* fn = argv[0]; fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); if (fd == -1) { fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno)); return 1; } const int len = strlen(fn); if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) { png = true; } } if (fd == -1) { usage(pname); return 1; } */ void const* mapbase = MAP_FAILED; ssize_t mapsize = -1; void const* base = 0; uint32_t w, h, f; size_t size = 0; int i = 0; int ntest = 100; char fname[256]; struct timeval tS, tE; double utime, mtime, seconds, useconds, average; gettimeofday(&tS, NULL); ScreenshotClient screenshot; for(i=0; i< ntest; i++) { sprintf(fname,"fb%02d.raw",i); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0664); if (screenshot.update() == NO_ERROR) { base = screenshot.getPixels(); w = screenshot.getWidth(); h = screenshot.getHeight(); f = screenshot.getFormat(); size = screenshot.getSize(); } else { printf("screenshot update failed - 2 \n"); /* const char* fbpath = "/dev/graphics/fb0"; int fb = open(fbpath, O_RDONLY); if (fb >= 0) { struct fb_var_screeninfo vinfo; if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) { uint32_t bytespp; if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) { size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp; w = vinfo.xres; h = vinfo.yres; size = w*h*bytespp; mapsize = offset + size; mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0); if (mapbase != MAP_FAILED) { base = (void const *)((char const *)mapbase + offset); } } } close(fb); } */ } if (base) { /* if (png) { SkBitmap b; b.setConfig(flinger2skia(f), w, h); b.setPixels((void*)base); SkDynamicMemoryWStream stream; SkImageEncoder::EncodeStream(&stream, b, SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality); SkData* streamData = stream.copyToData(); write(fd, streamData->data(), streamData->size()); streamData->unref(); } else */ { write(fd, &w, 4); write(fd, &h, 4); write(fd, &f, 4); write(fd, base, size); } } close(fd); if (mapbase != MAP_FAILED) { munmap((void *)mapbase, mapsize); } screenshot.release(); printf("%d:%s\n", i+1, fname); gettimeofday(&tE, NULL); seconds = tE.tv_sec - tS.tv_sec; useconds= tE.tv_usec- tS.tv_usec; utime = seconds * 1000000 + useconds; printf("Elapsed:%.2f\n", utime/1000000 ); usleep(1); } average = (double)ntest * 1000000 / utime ; printf("Elapsed:%.2f, Average:%.2f\n", utime/1000000, average); return 0; }