mem_transfer_intra_refs把数据从解码宏块窗口中复制到当前引用的参考帧上,用作帧内预测.
// 把MBs从图像中移动到当前的MB窗口,把数据从原始帧复制到当前宏块窗口的目的是留下一个备份,将来会用到 void mem_transfer_move_curr_ctu_group(henc_thread_t* et, int i, int j)//i,j are cu indexes { int width, height, component; // 目标窗口:MBs窗口(curr_mbs_wnd不知道是否可以看作是当前的宏块窗口) wnd_t* dst_wnd = &et->curr_mbs_wnd; byte * src; byte * dst; int src_stride, dst_stride; // 针对三个分量分别进行处理 for(component=Y_COMP;component<=V_COMP;component++) { // 源数据就是当前帧 src = WND_POSITION_2D(byte *, et->enc_engine->current_pict.img2encode->img, component, (i*et->ctu_width[component]), (j*et->ctu_height[component]), 0, et->ctu_width); // 目标缓存区就是当前宏块窗口 dst = WND_POSITION_2D(byte *, *dst_wnd, component, 0, 0, 0, et->ctu_width); src_stride = WND_STRIDE_2D(et->enc_engine->current_pict.img2encode->img, component); dst_stride = WND_STRIDE_2D(*dst_wnd, component); width = ((i+1)*et->ctu_width[component]<et->pict_width[component])?et->ctu_width[component]:(et->pict_width[component]-(i*et->ctu_width[component])); height = ((j+1)*et->ctu_height[component]<et->pict_height[component])?et->ctu_height[component]:(et->pict_height[component]-(j*et->ctu_height[component])); // 把源数据复制到当前宏宽窗口 mem_transfer_2d2d(src, dst, width, height, src_stride, dst_stride); } }
// 用于帧内参考 // 把数据从解码宏块窗口中复制到当前引用的参考帧上,以用于帧内预测 void mem_transfer_intra_refs(henc_thread_t* et, ctu_info_t* ctu) { int l; // 源窗口:参考帧 wnd_t *decoded_src_wnd = &et->enc_engine->curr_reference_frame->img; // 目标窗口:解码宏块窗口 wnd_t *decoded_dst_wnd = et->decoded_mbs_wnd[0]; int component = Y_COMP; // 长度 int src_stride = et->pict_width[component]; int dst_stride; // 源解码缓存 int16_t *decoded_buff_src; // 目标解码缓存 int16_t * decoded_buff_dst; // ctu的尺寸 int cu_size = ctu->size; int left_copy = 0, top_copy = 0; // 如果当前CTU的左边和上边都不存在,那么直接返回 if(!ctu->ctu_left && !ctu->ctu_top) return; // 对于每一个解码窗口(NUM_DECODED_WNDS == 7) for(l=0;l<NUM_DECODED_WNDS;l++) { // 对于该解码窗口中的每一个分量 for(component=Y_COMP;component<=V_COMP;component++) { int i, j; // 目标窗口就是解码的宏块窗口 decoded_dst_wnd = et->decoded_mbs_wnd[l]; // 长度 src_stride = WND_STRIDE_2D(*decoded_src_wnd, component); dst_stride = WND_STRIDE_2D(*decoded_dst_wnd, component); decoded_buff_src = WND_POSITION_2D(int16_t *, *decoded_src_wnd, component, ctu->x[component], ctu->y[component], 0, et->ctu_width); decoded_buff_dst = WND_POSITION_2D(int16_t *, *decoded_dst_wnd, component, 0, 0, 0, et->ctu_width); cu_size = et->ctu_width[component]; // 调整复制的长度 left_copy = top_copy = 0; if(ctu->ctu_left) left_copy += cu_size; if(ctu->ctu_left_bottom) left_copy += cu_size; if(ctu->ctu_top) top_copy += cu_size; if(ctu->ctu_top_right) top_copy += cu_size; if(left_copy>(et->pict_height[component]-ctu->y[component])) left_copy=(et->pict_height[component]-ctu->y[component]); if(top_copy>(et->pict_width[component]-ctu->x[component])) top_copy=(et->pict_width[component]-ctu->x[component]); decoded_buff_src-=(src_stride+1); decoded_buff_dst-=(dst_stride+1); //top-left square if(ctu->ctu_left && ctu->ctu_top) { *decoded_buff_dst = *decoded_buff_src; } decoded_buff_src++; decoded_buff_dst++; //bottom line // 复制底部的一行 for(i=0;i<top_copy;i++) decoded_buff_dst[i] = decoded_buff_src[i]; //memcpy(decoded_buff_dst, decoded_buff_src, top_copy*sizeof(decoded_buff_src[0])); // right column // 复制右边的一列 decoded_buff_src+=src_stride-1; decoded_buff_dst+=dst_stride-1; for(j=0;j<left_copy;j++) { decoded_buff_dst[j*dst_stride] = decoded_buff_src[j*src_stride]; } } } }