x264 - x264_frame_init_lowres

本文深入解析了x264中用于低分辨率帧初始化的关键算法,包括插值中心像素、边界扩展和成本估计初始化等步骤,旨在提高视频编码效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

void x264_frame_init_lowres( x264_t *h, x264_frame_t *frame )
{
    pixel *src = frame->plane[0];     // get luma plane
    int i_stride = frame->i_stride[0];  // line stride of luma plane
    int i_height = frame->i_lines[0];   // height of luma plane
    int i_width  = frame->i_width[0];   // width of luma plane


    // duplicate last row and column so that their interpolation doesn't have to 
    // be special-cased
    for( int y = 0; y < i_height; y++ )  //   // copy last column of luma pixel plane
        src[i_width+y*i_stride] = src[i_width-1+y*i_stride];
    // copy last row of luma pixel plane
    memcpy( src+i_stride*i_height, src+i_stride*(i_height-1), (i_width+1) * sizeof(pixel) );


    // interpolate center pixel of square consist of four points, for whole luma pixel plane
    // 如果以1/4像素坐标来看, 下面的代码就是插值斜对角 1/2 像素点, 

    //  为什么 不是 计算 F, H, V, HV呢?  有疑惑 。。。

    // see frame_init_lowres_core and diagram below
    // A       B       C         D       E ...
    //     *         *         *         *     ...
    // a       b       c         d       e ...
    //     *         *         *        *     ...
    // 0       1       2         3       4 ...
    // .......................................

    h->mc.frame_init_lowres_core( src, frame->lowres[0], frame->lowres[1], frame->lowres[2], frame->lowres[3],
                                  i_stride, frame->i_stride_lowres, frame->i_width_lowres, frame->i_lines_lowres );

   
    // expand 4 side for ipadh = 32 units(bytes), ipadv = 32 units(bytes)

    // 对frame->lowres[0], frame->lowres[1], frame->lowres[2], frame->lowres[3]

    // 1/2 像素帧分别进行四个边界的扩展, 每个边的扩展都是将该边的最后一个像素

    //  扩展32(PADH, PADV)字节
    x264_frame_expand_border_lowres( frame );


    memset( frame->i_cost_est, -1, sizeof(frame->i_cost_est) );


    // initialize for adaptive B-frame decision
    for( int y = 0; y < h->param.i_bframe + 2; y++ )
        for( int x = 0; x < h->param.i_bframe + 2; x++ )
            frame->i_row_satds[y][x][0] = -1;


    for( int y = 0; y <= !!h->param.i_bframe; y++ )
        for( int x = 0; x <= h->param.i_bframe; x++ )
            frame->lowres_mvs[y][x][0][0] = 0x7FFF;
}




static void frame_init_lowres_core( pixel *src0, pixel *dst0, pixel *dsth, pixel *dstv, pixel *dstc,
                                    intptr_t src_stride, intptr_t dst_stride, int width, int height )
{
    for( int y = 0; y < height; y++ )
    {
        pixel *src1 = src0+src_stride;
        pixel *src2 = src1+src_stride;
        for( int x = 0; x<width; x++ )
        {
            // slower than naive bilinear, but matches asm
#define FILTER(a,b,c,d) ((((a+b+1)>>1)+((c+d+1)>>1)+1)>>1)
            dst0[x] = FILTER(src0[2*x  ], src1[2*x  ], src0[2*x+1], src1[2*x+1]);
            dsth[x] = FILTER(src0[2*x+1], src1[2*x+1], src0[2*x+2], src1[2*x+2]);
            dstv[x] = FILTER(src1[2*x  ], src2[2*x  ], src1[2*x+1], src2[2*x+1]);
            dstc[x] = FILTER(src1[2*x+1], src2[2*x+1], src1[2*x+2], src2[2*x+2]);
#undef FILTER
        }
        src0 += src_stride*2;
        dst0 += dst_stride;
        dsth += dst_stride;
        dstv += dst_stride;
        dstc += dst_stride;
    }
}


void x264_frame_expand_border_lowres( x264_frame_t *frame )
{
    for( int i = 0; i < 4; i++ )
        plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_width_lowres, frame->i_lines_lowres, PADH, PADV, 1, 1, 0 );
}


static void ALWAYS_INLINE plane_expand_border( pixel *pix, int i_stride, int i_width, int i_height, int i_padh, int i_padv, int b_pad_top, int b_pad_bottom, int b_chroma )
{
#define PPIXEL(x, y) ( pix + (x) + (y)*i_stride )
    for( int y = 0; y < i_height; y++ )
    {
        /* left band */
        pixel_memset( PPIXEL(-i_padh, y), PPIXEL(0, y), i_padh>>b_chroma, sizeof(pixel)<<b_chroma );
        /* right band */
        pixel_memset( PPIXEL(i_width, y), PPIXEL(i_width-1-b_chroma, y), i_padh>>b_chroma, sizeof(pixel)<<b_chroma );
    }
    /* upper band */
    if( b_pad_top )
        for( int y = 0; y < i_padv; y++ )
            memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), (i_width+2*i_padh) * sizeof(pixel) );
    /* lower band */
    if( b_pad_bottom )
        for( int y = 0; y < i_padv; y++ )
            memcpy( PPIXEL(-i_padh, i_height+y), PPIXEL(-i_padh, i_height-1), (i_width+2*i_padh) * sizeof(pixel) );
#undef PPIXEL
}


// fast copy way
static void ALWAYS_INLINE pixel_memset( pixel *dst, pixel *src, int len, int size )
{
    uint8_t *dstp = (uint8_t*)dst;
    uint32_t v1 = *src;
    uint32_t v2 = size == 1 ? v1 + (v1 <<  8) : M16( src );
    uint32_t v4 = size <= 2 ? v2 + (v2 << 16) : M32( src );
    int i = 0;
    len *= size;


    /* Align the input pointer if it isn't already */
    if( (intptr_t)dstp & (WORD_SIZE - 1) )
    {
        if( size <= 2 && ((intptr_t)dstp & 3) )
        {
            if( size == 1 && ((intptr_t)dstp & 1) )
                dstp[i++] = v1;
            if( (intptr_t)dstp & 2 )
            {
                M16( dstp+i ) = v2;
                i += 2;
            }
        }
        if( WORD_SIZE == 8 && (intptr_t)dstp & 4 )
        {
            M32( dstp+i ) = v4;
            i += 4;
        }
    }


    /* Main copy loop */
    if( WORD_SIZE == 8 )
    {
        uint64_t v8 = v4 + ((uint64_t)v4<<32);
        for( ; i < len - 7; i+=8 )
            M64( dstp+i ) = v8;
    }
    for( ; i < len - 3; i+=4 )
        M32( dstp+i ) = v4;


    /* Finish up the last few bytes */
    if( size <= 2 )
    {
        if( i < len - 1 )
        {
            M16( dstp+i ) = v2;
            i += 2;
        }
        if( size == 1 && i != len )
            dstp[i] = v1;
    }
}

<think>好的,用户想了解naturalearth_lowres数据集的定义或用途。首先,我需要回忆一下自己对这个数据集的了解。记得在Geopandas的文档中,naturalearth_lowres是一个内置的示例数据集,通常用于地理空间数据分析和可视化教学。 接下来,我需要确认它的具体内容。根据引用[2]提到的,用户可能已经接触过这个数据集,因为它用于展示人口密度的地图。naturalearth_lowres通常包含国家边界的矢量数据,比如每个国家的几何形状(多边形或多边形集合)以及一些属性信息,比如国家名称、人口估计、大洲分类、GDP等。这个数据集的分辨率较低,适合快速绘图和演示,不需要处理大量细节。 然后,考虑用户可能的实际应用场景。用户可能在使用Geopandas进行地图绘制时遇到这个数据集,或者在教程中看到相关代码示例。例如,引用[2]中的代码加载了人口数据并创建了地图,可能用到了类似的数据集。需要说明它的主要用途,比如教学、原型开发、快速可视化测试等,以及它的优点,比如方便获取、结构清晰、数据量适中。 另外,用户可能想知道如何获取和使用这个数据集。根据引用[3]提到的geopandas-tutorial项目,可能这个数据集是通过Geopandas的datasets模块提供的,使用gpd.datasets.get_path('naturalearth_lowres')来加载。需要给出具体的代码示例,并解释每个步骤的作用,比如读取数据、筛选数据、添加对数变换列、绘图等,如引用[2]中的代码所示。 还要注意数据集的特性,比如低分辨率适合全球范围的可视化,但不适合需要高精度的分析。同时,数据集中可能包含一些需要处理的部分,比如南极洲的数据可能不相关,所以示例中排除了它,如引用[2]中的代码所示。 最后,确保回答结构清晰,分点说明定义、数据内容、用途、使用示例,并引用相关的资料来支持。同时,按照用户要求生成相关问题,帮助用户进一步探索。</think>[用户可见层] ### naturalearth_lowres 数据集解析 #### 定义与数据内容 `naturalearth_lowres` 是 **地理空间数据分析库GeoPandas内置的全球矢量数据集**,提供国家/地区级别的低分辨率地理边界数据。其核心特征包括: - **数据格式**: 矢量地图数据(`GeoDataFrame` 格式) - **分辨率**: 1:110m(适用于全球范围可视化) - **属性字段**: - `geometry`(国家/地区边界几何形状) - `pop_est`(人口估计值) - `continent`(所属大洲) - `gdp_md_est`(GDP估算值,单位:百万美元)[^2][^3] #### 主要用途 1. **地理可视化快速原型开发** 通过一行代码即可加载全球地图数据,常用于教学演示和基础地图绘制: ```python world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) world.plot() ``` 2. **空间数据分析基础模板** 提供国家名称、人口、经济指标等字段,支持关联其他数据进行空间统计分析(如引用[2]中的人口密度可视化示例)。 3. **GIS功能测试** 用于验证坐标参考系转换、空间连接、缓冲区分析等地理处理流程的标准化测试数据[^3]。 #### 典型应用示例 ```python import geopandas as gpd # 加载数据集并预处理 world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) world = world[(world.pop_est > 0) & (world.name != "Antarctica")] # 创建人口对数变换可视化 world['pop_est_log'] = np.log(world['pop_est']) world.plot(column='pop_est_log', legend=True, cmap='OrRd') ``` 此代码会生成带颜色渐变效果的全球人口分布图(如引用[2]的实现逻辑)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值