x264 代码中的一个坑 和 指针;

来源:互联网 发布:男孩被父砍 知乎 编辑:程序博客网 时间:2024/05/28 18:43

开源代码就是开源代码,不是工程代码;
今天在看x264的 x264_cqm_init 这个函数的代码时,发现里面有个坑;

先来看下 x264_h 里面有这样几个变量:

 

/* quantization matrix for decoding, [cqm][qp%6][coef] */    int             (*dequant4_mf[4])[16];   /* [4][6][16] */    int             (*dequant8_mf[2])[64];   /* [2][6][64] */    /* quantization matrix for trellis, [cqm][qp][coef] */    int             (*unquant4_mf[4])[16];   /* [4][52][16] */    int             (*unquant8_mf[2])[64];   /* [2][52][64] */    /* quantization matrix for deadzone */    uint16_t        (*quant4_mf[4])[16];     /* [4][52][16] */    uint16_t        (*quant8_mf[2])[64];     /* [2][52][64] */    uint16_t        (*quant4_bias[4])[16];   /* [4][52][16] */    uint16_t        (*quant8_bias[2])[64];   /* [2][52][64] */


在 x264_cqm_init 中 有这样的代码;

for( int i = 0; i < 4 + num_8x8_lists; i++ )    {        int size = i<4 ? 16 : 64;        int j;        for( j = (i<4 ? 0 : 4); j < i; j++ )            if( !memcmp( h->pps->scaling_list[i], h->pps->scaling_list[j], size*sizeof(uint8_t) ) )                break;        if( j < i )        {            h->  quant4_mf[i] = h->  quant4_mf[j];            h->dequant4_mf[i] = h->dequant4_mf[j];            h->unquant4_mf[i] = h->unquant4_mf[j];        }        else        {            CHECKED_MALLOC(udctcoef (*)[16], h->  quant4_mf[i], (QP_MAX+1)*size*sizeof(udctcoef) );//实际跟踪发现,i会等于4;而 quant4_mf 长度明确定义为4,这岂不是越界了?我准备怀疑我的C语言水平了            CHECKED_MALLOC(int (*)[16], h->dequant4_mf[i],  6*size*sizeof(int) );            CHECKED_MALLOC(int (*)[16], h->unquant4_mf[i], (QP_MAX+1)*size*sizeof(int) );        }        .        .        .     }

在后面对 h->quant4_mf 的访问过程如下

h->quant4_mf[i_list][q][i] = j = SHIFT(quant4_mf[i_list][q%6][i], q/6 - 1);


其中 i_list 范围是 0-3;这里的做法和定义是一致的;

经过仔细地研究代码,发现奥秘是,在上面分配内存的过程中,在一个循环内,实际上是先后给 unquant4_mf[4] 和 unquant8_mf[2] 申请内存和设置内存地址;
num_8x8_lists 实际是 2, 也就是循环的前4次是处理 unquant4_mf[4], 后两次是处理 unquant8_mf[2];
这也就是在 x264_h 相关变量这么定义的原因;
对于其余几个类似变量也是同样的情形。

所以,x264_h 结构体里面的定义 有些地方还真不是可以随便改动的,弄不好就会踩到坑;

这里也同时提示了 指针的特殊用法;

{unsigned char v3[2][2][3][4] = {{{{1,2,3,4},{5,6,7,8},{9,10,11,12}},{{13,14,15,16},{17,18,19,20},{21,22,23,24}}},{{{1,2,3,4},{5,6,7,8},{9,10,11,12}},{{13,14,15,16},{17,18,19,20},{21,22,23,24}}}};unsigned char (*p3[2])[2][3][4];//here//p3[0] = p[1] = 0xccccccccint d0 = 1;//0-1p3[d0] = (unsigned char (*)[2][3][4])v3[0];int d1/*0-1*/, d2/*0-2*/, d3/*0-3*/;//visit [1][2][3]d1 = 1, d2 = 2, d3 = 3;printf("p3[%d][0][%d][%d][%d]=%d\n", d0, d1, d2, d3, p3[d0][0][d1][d2][d3]);//or printf("p3[%d][0][%d][%d][%d]=%d\n", d0, d1, d2, d3, (*p3[d0])[d1][d2][d3]);//visit [1][3][2], offset = 1*3*4 + 3*4 + 2; actually visit v3[1][0][0][2]d1 = 1, d2 = 3,d3 = 2;printf("p3[%d][0][%d][%d][%d]=%d\n", d0, d1, d2, d3, p3[d0][0][d1][d2][d3]);//or printf("p3[%d][0][%d][%d][%d]=%d\n", d0, d1, d2, d3, (*p3[d0])[d1][d2][d3]);//usage in x264int 16x = 64;unsigned char (*p4[4])[16];p4[3] = malloc(16 * 16x);//visit p4[3][2][5], offset is 2*15 + 5;printf("p4[3][2][5]=%d\n", p4[3][2][5]);}



 

原创粉丝点击