Android平台中统计C/C++覆盖率

下面所涉及的实验平台
ubuntu host电脑
android设备

首先,我们回顾一下在ubuntu中如何实现覆盖率统计

rgb2yuv.cpp是本次试验用的代码

编译

1、命令行编译

gcc rgb2yuv.cpp -fprofile-arcs -ftest-coverage

2、或者用makefile编译

edit : rgb2yuv.o
    gcc rgb2yuv.o -o edit -fprofile-arcs

rgb2yuv.o : rgb2yuv.cpp
    gcc -c -fprofile-arcs -ftest-coverage rgb2yuv.cpp

以上编译会产生下面几个文件

xxx@xxx:~/ca07/frameworks/av/cmds/camerad$ ./edit 
-rwxrwxr-x 1 qyang qyang  28777  215 15:10 edit*
-rw-rw-r-- 1 qyang qyang    126  214 16:42 Makefile
-rw-rw-r-- 1 qyang qyang   2897  214 16:49 rgb2yuv.cpp
-rw-rw-r-- 1 qyang qyang   2964  215 15:10 rgb2yuv.gcno
-rw-rw-r-- 1 qyang qyang   6760  215 15:10 rgb2yuv.o

其中edit为产生的可执行文件,rgb2yuv.gcno是由-ftest-coverage产生的,它包含了重建基本块图和相应的块的源码的行号的信息。

运行程序并收集覆盖数据

xxx@xxx:~/ca07/frameworks/av/cmds/camerad$ ./edit

程序结束后会产生下面的文件
rgb2yuv.gcda
此文件由 -fprofile-arcs 编译参数的编译后的文件运行所产生的,它记录了每行代码执行的次数和其他的概要信息。

生成报告

lcov -c -d ./ -o res.info --rc lcov_branch_coverage=1
genhtml -o report res.info --rc lcov_branch_coverage=1

上面完成后会在目录产生res.info和report目录,使用浏览器打开report目录中的index.html,即可看到覆盖率信息。
这里写图片描述

在Android平台中统计C/C++覆盖率

Android.mk 按下面的样式

include $(CLEAR_VARS)

LOCAL_SRC_FILES := rgb2yuv.cpp

LOCAL_SHARED_LIBRARIES := libutils libgui libbinder libui libcutils liblog

LOCAL_CFLAGS += -fprofile-arcs -ftest-coverage
LOCAL_LDFLAGS := -fprofile-arcs

LOCAL_MODULE:= rgb2yuv

include $(BUILD_EXECUTABLE)

编译

编译完后rgb2yuv.gcno文件在out目录中
out/target/product/top6735_35gu_l1/obj/EXECUTABLES/rgb2yuv_intermediates/rgb2yuv.gcno
将此文件copy到代码目录中

部署

将编译完的rgb2yuv push到设备中
adb push ~/ca07/out/target/product/top6735_35gu_l1/system/bin/rgb2yuv /mnt/hd/

运行

shell@android:/mnt/hd $ export GCOV_PREFIX=/mnt/hd/
shell@android:/mnt/hd $ ./rgb2yuv                                              
hello world

产生的文件在下面路径中
/mnt/hd/home/qyang/ca07/out/target/product/top6735_35gu_l1/obj/EXECUTABLES/rgb2yuv_intermediates/rgb2yuv.gcda

PS:
1、一定要设置GCOV_PREFIX环境,否则会在根目录下产生gcda文件,但根目录只读,会导致产生失败。
2、设置的目录一定要有写权限,如果目录指向sdcard卡,还必须在AndroidManifast.xml中申明权限。

shell@android:/mnt/hd $ ./rgb2yuv                                              
hello world
profiling:/home:Cannot create directory
profiling:/home/qyang/ca07/out/target/product/top6735_35gu_l1/obj/EXECUTABLES/rgb2yuv_intermediates/rgb2yuv.gcda:Skip

产生报告

adb pull /mnt/hd/home/qyang/ca07/out/target/product/top6735_35gu_l1/obj/EXECUTABLES/rgb2yuv_intermediates/rgb2yuv.gcda

有了gcda文件,和gcno文件,再产生html报告就和上面一样了。

lcov -c -d ./ -o res.info --rc lcov_branch_coverage=1
genhtml -o report res.info --rc lcov_branch_coverage=1

容易被忽略的地方

一定要等到程序正常停止退出才会产生gcda文件,如果Ctl+C中断,或crash,都不会有这个文件。

附件
这里写图片描述

// rgb2yuv.cpp
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>


static  int RGB2YUV_YR[256], RGB2YUV_YG[256], RGB2YUV_YB[256];
static  int RGB2YUV_UR[256], RGB2YUV_UG[256], RGB2YUV_UBVR[256];
static  int RGB2YUV_VG[256], RGB2YUV_VB[256];

//
// Table used for RGB to YUV420 conversion
//
void InitLookupTable()
{

    int i=0;

    for (i = 0; i < 256; i++) RGB2YUV_YR[i] = (float)65.481 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_YG[i] = (float)128.553 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_YB[i] = (float)24.966 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_UR[i] = (float)37.797 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_UG[i] = (float)74.203 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_VG[i] = (float)93.786 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_VB[i] = (float)18.214 * (i << 8);
    for (i = 0; i < 256; i++) RGB2YUV_UBVR[i] = (float)112 * (i << 8);

}

//
//  Convert from  RGB24 to YUV420
//
int ConvertRGB2YUV(const int w, const int h, const uint8_t *bmp, uint8_t *yuv)
{
    uint8_t *u,*v;
    const uint8_t *r = bmp;

    if (!yuv || !bmp)
        return -1;

    uint8_t *vv = yuv + w * h;
    uint8_t *uu = vv + w*h/4;

    u = uu;
    v = vv;

    //Get YUV values for rgb values...
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x += 2) {

            register uint8_t rd = *r++;
            register uint8_t gd = *r++;
            register uint8_t bd = *r++;
            r++;

            *yuv++ = (RGB2YUV_YR[rd]  + RGB2YUV_YG[gd] + RGB2YUV_YB[bd]   + 1048576) >> 16;

            rd = *r++;
            gd = *r++;
            bd = *r++;
            r++;
            *yuv++ = (RGB2YUV_YR[rd]  + RGB2YUV_YG[gd] + RGB2YUV_YB[bd]   + 1048576) >> 16;

            if (y & 1) {
                *u++ = (-RGB2YUV_UR[rd]  - RGB2YUV_UG[gd] + RGB2YUV_UBVR[bd] + 8388608) >> 16;
                *v++ = ( RGB2YUV_UBVR[rd]- RGB2YUV_VG[gd] - RGB2YUV_VB[bd]   + 8388608) >> 16;
            }
        }
    }

    // Now sample the U & V to obtain YUV 4:2:0 format
    // Sampling mechanism...
    /*
        @  ->  Y
        #  ->  U or V

        @   @   @   @
        #       #
        @   @   @   @

        @   @   @   @
        #       #
        @   @   @   @
    */

/*
    uint8_t *pu1,*pu2,*pu3,*pu4;
    uint8_t *pv1,*pv2,*pv3,*pv4;

    // Get the right pointers...
    u = yuv + w*h;
    v = u + (w*h)/4;

    // For U
    pu1 = uu;
    pu2 = pu1 + 1;
    pu3 = pu1 + w;
    pu4 = pu3 + 1;

    // For V
    pv1 = vv;
    pv2 = pv1 + 1;
    pv3 = pv1 + w;
    pv4 = pv3 + 1;

    // Do sampling....
    for (int i = 0; i < h; i +=2) {
        for (int j = 0; j < w; j+=2) {

            *u++ = (*pu1+*pu2+*pu3+*pu4) >> 2;
            *v++ = (*pv1+*pv2+*pv3+*pv4) >> 2;

            pu1 += 2;
            pu2 += 2;
            pu3 += 2;
            pu4 += 2;

            pv1 += 2;
            pv2 += 2;
            pv3 += 2;
            pv4 += 2;
        }
        pu1 += w;
        pu2 += w;
        pu3 += w;
        pu4 += w;

        pv1 += w;
        pv2 += w;
        pv3 += w;
        pv4 += w;
    }
*/
    return 0;
}

int main(int argc, char* const argv[])
{
    InitLookupTable();
    InitLookupTable();
    printf("hello world\n");
    sleep(10);
    ConvertRGB2YUV(0, 0, NULL, NULL);
    ConvertRGB2YUV(0, 0, NULL, NULL);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值