x264中的decimate_score

 为了减少残差系数使用的编码比特,x264中使用了一种方法--decimation。原话是这样子的:

Writing the 16 CBFs in an i16x16 block is quite costly, so decimation can save many bits. More useful with CAVLC, but still useful with CABAC. 中心思想是如果一个16x16块的非零残差系数个数很少且最大绝对值不超过1(用一个score来衡量),直接将其所有4x4块的残差系数置为0,这样子就不要为该16x16块发送16个cbf;

对于亮度,如果是8x8块,则score<4时,将残差系数全置为0;

                    如果是16x16块,则score<6时,将残差系数全置为0;

对于色度,则score<7时,将残差系数全置为0;

该技术一般用于帧间宏块,总共在下面几个函数应用:

x264_mb_encode_i16x16;

x264_macroblock_encode_p8x8_internal;

x264_macroblock_probe_skip_internal;

x264_macroblock_encode_internal;

x264_mb_encode_chroma_internal;

以x264_mb_encode_i16x16为例来看看:

static void x264_mb_encode_i16x16( x264_t *h, int p, int i_qp )

{

    pixel *p_src = h->mb.pic.p_fenc[p];

    pixel *p_dst = h->mb.pic.p_fdec[p];

 

    ALIGNED_ARRAY_N( dctcoef, dct4x4,[16],[16] );

    ALIGNED_ARRAY_N( dctcoef, dct_dc4x4,[16] );

 

    int nz, block_cbp = 0;

    int decimate_score = h->mb.b_dct_decimate ? 0 : 9;//I帧设置为9,p帧设置为0;

    int i_quant_cat = p ? CQM_4IC : CQM_4IY;

    int i_mode = h->mb.i_intra16x16_pred_mode;

 

    if( h->mb.b_lossless )

        x264_predict_lossless_16x16( h, p, i_mode );

    else

        h->predict_16x16[i_mode]( h->mb.pic.p_fdec[p] );

 

    if( h->mb.b_lossless )

    {

<think>我们正在处理一个关于STM32的CMSIS-DSP库中arm_fir_decimate_init_f32函数的使用问题,用户遇到了hardfault错误。我们需要解释如何正确初始化该函数以避免此错误。首先,了解函数功能:arm_fir_decimate_init_f32用于初始化一个FIR抽取滤波器。该函数定义如下:```carm_statusarm_fir_decimate_init_f32(arm_fir_decimate_instance_f32*S,uint16_tnumTaps,uint8_tM,constfloat32_t*pCoeffs,float32_t*pState,uint32_tblockSize)```参数说明:-S:指向滤波器实例结构体的指针-numTaps:滤波器系数的个数(抽头数)-M:抽取因子(例如,M=2表示每两个输入样本产生一个输出样本)-pCoeffs:指向滤波器系数数组的指针(长度应为numTaps)-pState:指向状态缓冲区的指针(用于存储滤波器的内部状态,长度应为numTaps+blockSize-1)-blockSize:每次调用滤波函数时处理的输入样本数量(注意:输出样本数为blockSize/M,因此blockSize必须能被M整除)避免hardfault的常见原因:1.指针为空(NULL)或未初始化:确保S、pCoeffs、pState都不是NULL,并且已经分配了内存。2.内存对齐问题:对于Cortex-M系列,访问未对齐的内存地址可能导致hardfault。确保pCoeffs和pState数组在内存中正确对齐(对于float32_t,通常要求4字节对齐)。3.数组大小不足:状态缓冲区pState的大小必须至少为`numTaps+blockSize-1`。如果分配不足,可能导致缓冲区溢出。4.blockSize不是M的整数倍:函数要求blockSize必须能被M整除,否则会导致未定义行为。5.堆栈溢出:如果这些数组分配在堆栈上且过大,可能导致堆栈溢出。考虑使用静态数组或动态分配(从堆中)。正确使用步骤:1.定义滤波器实例:`arm_fir_decimate_instance_f32fir_decimate_inst;`2.分配系数数组:`float32_tfir_coeffs[NUM_TAPS]={...};//滤波器系数`3.分配状态缓冲区:`float32_tfir_state_buffer[NUM_TAPS+BLOCK_SIZE-1];`或者动态分配。4.确保内存对齐:可以使用`__attribute__((aligned(4)))`(GCC)或`__align(4)`(IAR)来确保对齐,或者使用CMSIS提供的宏。5.调用初始化函数:```carm_statusstatus=arm_fir_decimate_init_f32(&fir_decimate_inst,NUM_TAPS,M,fir_coeffs,fir_state_buffer,BLOCK_SIZE);```检查返回值(ARM_MATH_SUCCESS表示成功)。6.使用:调用`arm_fir_decimate_f32(&fir_decimate_inst,input,output,blockSize);`时,确保input和output数组大小正确。特别注意:状态缓冲区在初始化后会被函数内部使用,因此不能是局部变量(除非是静态的)且在多次调用滤波函数之间要保持不变。如果仍然遇到hardfault,可以使用调试器检查故障发生时的寄存器值(如LR,PC)以确定故障原因,或者检查内存访问错误。相关问题:1.如何为FIR抽取滤波器设计合适的滤波器系数?2.在STM32上使用CMSIS-DSP库时,如何优化内存使用以避免堆栈溢出?3.如何调试STM32上的hardfault错误?</think>### 正确使用 `arm_fir_decimate_init_f32` 避免 STM32 HardFault #### 1. **函数作用与参数解析** `arm_fir_decimate_init_f32` 是 CMSIS-DSP 库中用于初始化**浮点型 FIR 抽取滤波器**的函数[^1]。其原型如下: ```c arm_status arm_fir_decimate_init_f32( arm_fir_decimate_instance_f32 * S, // 滤波器实例指针 uint16_t numTaps, // 滤波器抽头数(系数数量) uint8_t M, // 抽取因子(如 M=2 表示 2:1 抽取) const float32_t * pCoeffs, // 滤波器系数数组指针 float32_t * pState, // 状态缓冲区指针 uint32_t blockSize // 每次处理的输入样本数 ); ``` #### 2. **避免 HardFault 的关键配置** ##### (1) **内存对齐要求** STM32 的 Cortex-M 内核要求浮点数组必须 **4 字节对齐**。未对齐访问会触发 HardFault: ```c // 正确做法:使用 __attribute__((aligned(4))) float32_t coeffs[NUM_TAPS] __attribute__((aligned(4))) = {...}; float32_t stateBuffer[STATE_SIZE] __attribute__((aligned(4))); ``` ##### (2) **状态缓冲区大小计算** 状态缓冲区大小必须满足: `STATE_SIZE = numTaps + blockSize - 1` **错误示例**: ```c // 若 numTaps=32, blockSize=64,则至少需要 32+64-1=95 个 float float32_t stateBuffer[80]; // 太小!会内存越界触发 HardFault ``` ##### (3) **blockSize 限制** `blockSize` 必须是 **抽取因子 M 的整数倍**,否则计算输出时越界: ```c // 错误:M=3 但 blockSize=10 (10 % 3 != 0) arm_fir_decimate_init_f32(&fir, 32, 3, coeffs, state, 10); // 触发 HardFault ``` ##### (4) **指针有效性验证** 所有指针必须非空且指向有效内存: ```c if (pCoeffs == NULL || pState == NULL) { // 立即返回错误,避免后续崩溃 return ARM_MATH_ARGUMENT_ERROR; } ``` #### 3. **完整初始化示例** ```c #define NUM_TAPS 32 // 滤波器系数数量 #define M_FACTOR 4 // 4:1 抽取 #define BLOCK_SIZE 64 // 输入样本块大小(必须是 M_FACTOR 的倍数) // 4 字节对齐的数组(关键!) float32_t firCoeffs[NUM_TAPS] __attribute__((aligned(4))) = {...}; float32_t firState[NUM_TAPS + BLOCK_SIZE - 1] __attribute__((aligned(4))); arm_fir_decimate_instance_f32 fir; void init_filter() { arm_status status = arm_fir_decimate_init_f32( &fir, // 实例指针 NUM_TAPS, // 抽头数 M_FACTOR, // 抽取因子 firCoeffs, // 系数数组 firState, // 状态缓冲区 BLOCK_SIZE // 输入块大小 ); if (status != ARM_MATH_SUCCESS) { // 处理初始化失败(如参数检查) Error_Handler(); } } ``` #### 4. **HardFault 调试建议** 若仍触发 HardFault: 1. 检查 **堆栈溢出**:增大 `.ld` 文件中的堆栈大小。 2. 验证 **系数来源**:确保系数数组未被意外修改。 3. 使用 **断点调试**:在函数调用前检查所有指针地址是否合法。 4. 启用 **MemManage Fault** 中断:通过 SCB->SHCSR 寄存器定位非法访问地址。 > **关键点总结**:内存对齐、缓冲区尺寸、参数有效性是避免 HardFault 的核心[^1]。 --- ### 相关问题 1. 如何为 ARM CMSIS-DSP 的 FIR 滤波器设计合适的滤波器系数? 2. STM32 出现 HardFault 时有哪些快速定位错误的方法? 3. 在实时音频处理中如何优化 FIR 抽取滤波器的计算效率? [^1]: 配置参数时需严格遵循内存对齐与尺寸规则,否则会触发硬件错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值