adb 可以与手机或模拟器交換数据,比如传文件、调试等等。
之前在网上看到帖子可以修改adb抓屏,自己也实现了一个,记录一下。
原理:
在Eclipse中通过DDMS可以直接抓屏,说明ADB是可以取到机子的FrameBuffer的。
修改 adb/commandline.c ,响应自定义的参数调用 int fd = adb_connect("framebuffer:"); 抓屏,这里得到的是像素数据,还要用 ffmpeg 转成图片格式,当然也可以自己在adb里面打包成常见的图像格式,不过那没有必要。
这里传不了压缩包,就把 patch 文件贴出来:
diff -u _patch/adb/commandline.c adb/commandline.c
--- _patch/adb/commandline.c 2012-02-16 11:36:21.427198001 +0800
+++ adb/commandline.c 2012-02-16 14:40:39.303198001 +0800
@@ -226,6 +226,55 @@
}
}
+static void read_and_dumphex(int fd, int size)
+{
+ char buf[4096];
+ int len;
+ int i;
+
+ while(fd >= 0) {
+ len = adb_read(fd, buf, 4096);
+
+ if(len == 0) {
+ break;
+ }
+
+ if(len < 0) {
+ if(errno == EINTR) continue;
+ break;
+ }
+
+ /* we want to output to stdout, so no adb_write here !! */
+ for(i=0; i<len; i++)
+ fprintf(stderr,"%c", buf[i]);
+
+ size -= len;
+ if(size <= 0)
+ break;
+ }
+
+}
+static void read_and_dumpfile(int fd, int size, int lfd) {
+ char buf[4096];
+ int len;
+
+ while(fd >= 0) {
+ len = adb_read(fd, buf, 4096);
+ if(len == 0) {
+ break;
+ }
+
+ if(len < 0) {
+ if(errno == EINTR) continue;
+ break;
+ }
+ writex(lfd, buf, len);
+ }
+}
+static int read_int_little(unsigned char *p) {
+ return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
+}
+
#ifdef SH_HISTORY
int shItemCmp( void *val, void *idata )
{
@@ -843,6 +892,63 @@
/* adb_connect() commands */
+ if(!strcmp(argv[0], "framebuffer")) {
+ int fd = adb_connect("framebuffer:");
+
+ if (fd >= 0) {
+ unsigned char info[48];
+ int size = 0;
+ int len;
+ int v = -1;
+ len = adb_read(fd, info, 4);
+ if (len == 4) {
+ v = read_int_little(info);
+ }
+ if (v == 1) {
+ len = adb_read(fd, info, 12*4);
+ if (len != 12*4) v = -1;
+ } else if (v==16) {
+ len = adb_read(fd, info, 3*4);
+ if (len != 3*4) v = -1;
+ }
+ if (v == 1) {
+ size = read_int_little(&info[4]);
+
+ fprintf(stderr, "\nbpp=%d width=%d height=%d format=R(%d,%d)-B(%d,%d)-G(%d,%d)-A(%d,%d)\n", read_int_little(info),
+ read_int_little(&info[8]), read_int_little(&info[12]),
+ read_int_little(&info[16]), read_int_little(&info[20]),
+ read_int_little(&info[24]), read_int_little(&info[28]),
+ read_int_little(&info[32]), read_int_little(&info[36]),
+ read_int_little(&info[40]), read_int_little(&info[44])
+ );
+ } else if (v == 16) {
+ size = read_int_little(info);
+ fprintf(stderr, "\n16 widht=%d, height=%d format=rgb565\n", read_int_little(&info[4]),
+ read_int_little(&info[8])
+ );
+ }
+
+ if (v==1 || v==16) {
+ if (argc==2) {
+ int fo = adb_creat(argv[1], 0644);
+ if (fo >= 0) {
+ read_and_dumpfile(fd, size, fo);
+ adb_close(fo);
+ adb_close(fd);
+ return 0;
+ }
+ }
+ read_and_dumphex(fd, size);
+ adb_close(fd);
+ return 0;
+ }
+ }
+
+ fprintf(stderr,"error: %s\n", adb_error());
+ return 1;
+ }
+
+
if(!strcmp(argv[0], "devices")) {
char *tmp;
snprintf(buf, sizeof buf, "host:%s", argv[0]);
用法:
# by nxliao(2012-02-16)
# Command:
# get pixels
$ adb framebuffer yourfile_path
# you'll see information like this
#
# bpp=32 width=480 height=800 format=R(16,8)-B(0,8)-G(8,8)-A(24,8)
# convert to image
#
# -pix_fmt format set pixel format, 'list' as argument shows all the pixel formats supported
#
$ ffmpeg -pix_fmt bgra -s 480x800 -f rawvideo -i yourfile_path -f image2 -y yourimage_path.png
如果知道了屏幕参数,也可以直接用 adb pull 把帧数据导出来,再转成图片。

6万+

被折叠的 条评论
为什么被折叠?



