改装Adb用于抓屏

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 把帧数据导出来,再转成图片。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值