📄 deblock_ref.c
字号:
// -------------------------------------------------------------------// ?2005 Stream Processors, Inc. All rights reserved.// This Software is the property of Stream Processors, Inc. (SPI) and// is Proprietary and Confidential. It has been provided under// license for solely use in evaluating and/or developing code for a// stream processor device. Any use of the Software to develop code// for a semiconductor device not manufactured by or for SPI is// prohibited. Unauthorized use of this Software is strictly// prohibited.//// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES ARE GIVEN,// WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WARRANTIES OR// MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE,// NONINFRINGEMENT AND TITLE. RECIPIENT SHALL HAVE THE SOLE// RESPONSIBILITY FOR THE ADEQUATE PROTECTION AND BACK-UP OF ITS DATA// USED IN CONNECTION WITH THIS SOFTWARE. IN NO EVENT WILL SPI BE// LIABLE FOR ANY CONSEQUENTIAL DAMAGES WHATSOEVER, INCLUDING LOSS OF// DATA OR USE, LOST PROFITS OR ANY INCIDENTAL OR SPECIAL DAMAGES,// ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS// SOFTWARE, WHETHER IN ACTION OF CONTRACT OR TORT, INCLUDING// NEGLIGENCE. SPI FURTHER DISCLAIMS ANY LIABILITY WHATSOEVER FOR// INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS OF ANY THIRD// PARTY.// -------------------------------------------------------------------//--------------------------------------------------------------------// $File: //depot/main/software/demo/deblock/src/deblock_ref.c $// $Revision: #1 $// $DateTime: 2007/12/10 16:59:57 $//// Description:// Simplified implementation for loop filter (as compared to// previous VSofts data structures).// // Current version fully supports Baseline profile, but lacks support// for the following Main Profile features: B-frames and Interlaced// frames.//--------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include "spi_common.h"#include "encoder_tables.h"#include "mb_info.h"#include "encoder_context.h"//-------------------------------------------------------------------// Local defines, macros, and constants//-------------------------------------------------------------------#define CLIP0_255(x) (IClip(0, 255, (x)))#define IClip(Min, Max, Val) (((Val)<(Min)) ? (Min) : (((Val)>(Max)) ? (Max) : (Val)))// Indexed with [direction][edge][4x4 block]// direction: 0 - vertical, 1 - horizontal// edge: 0-3, from left to right (dir = 0) or top to bottom (dir = 1)// block: 0-3: which block within a particular edge, from top to// bottom for dir=0, and left to right for dir=1.typedef unsigned char S_BOUNDARY_STRENGTH_REF[2][4][4];//#define DEBUG_OUTPUT#ifdef DEBUG_OUTPUTofstream dbgfile;#define DEBUG_FILENAME "new_lf.txt"#endif//-------------------------------------------------------------------// Local protocols//-------------------------------------------------------------------void CalcBoundaryStrength(S_BLK_MB_INFO *MBInfo, S_BLK_MB_INFO *MBInfoLeft, S_BLK_MB_INFO *MBInfoTop, S_BOUNDARY_STRENGTH_REF *BSRef, int disable_deblocking_filter_idc);void DeblockMB(S_BOUNDARY_STRENGTH_REF *BSRef, int QPyCurr, int QPyLeft, int QPyTop, int alpha_c0_offset, int beta_offset, yuv_frame_t *frame, int MBx, int MBy, int DontFilterVertEdges, int DontFilterHorzEdges);void EdgeLoopLuma(unsigned char* SrcPtr, unsigned char Strength[4], int QP, int AlphaC0Offset, int BetaOffset, int PtrInc, int inc);void EdgeLoopChroma(unsigned char* SrcPtr, unsigned char Strength[4], int QP, int AlphaC0Offset, int BetaOffset, int PtrInc, int inc);static void pad_deblock_out_frame(yuv_frame_t *in_out, int PadAmount);// Make BSRef a global var, useful for debuggingS_BOUNDARY_STRENGTH_REF *BSRef = NULL;#ifdef DEBUGunsigned char *qp_av_ref = NULL;#endif//====================================================================// The main MB-filtering function. The basic strategy is to// translate all the information in the VSofts data structure that// are passed to the function into a new simplified data structure.//--------------------------------------------------------------------void deblock_frame_ref( encoder_context_t *p_enc ){ // Read necessary information from encoder context struct (p_enc) S_BLK_MB_INFO *pBlkMBInfo = p_enc->pBlkMBInfo; int disable_deblocking_filter_idc = p_enc->loopfilter_params.disable_flag; int slice_alpha_c0_offset = p_enc->loopfilter_params.alpha_c0_offset; int slice_beta_offset = p_enc->loopfilter_params.beta_offset; yuv_frame_t *frame = p_enc->pRecFrame; // Input & Output // Do not access p_enc directly below this line int MBNumX = frame->image_width>>4; int MBNumY = frame->image_height>>4; int MBcurr, MBcurrLeft, MBcurrTop; int s, x, y, m, CurrStripSize; // [UJK} Make a temporary assumption on strip size. I expect it // to be more like 100 for SP-16, but am setting it to a lower // value here to increase testing of strip-mining code in the // meantime. int StripSize = 24; // = getStripSize(); // The StripSize variable doesn't account for the extra boundary // macroblock that needs to be processed in order to stitch // together the filtering of two adjacent strips (See comments // below on the "Main stream loop"). So we have to add +1 when we // use this value in many places. int NumStrips = (MBNumX / StripSize) + ((MBNumX % StripSize) ? 1 : 0); BSRef = (S_BOUNDARY_STRENGTH_REF *)spi_malloc(MBNumX * MBNumY * sizeof(*BSRef)); if (!BSRef) { spi_printf("Error allocating memory for loop filter boundary strength indices!! Exiting..."); spi_exit(-1); }#ifdef DEBUG qp_av_ref = (unsigned char *)spi_malloc(MBNumX * MBNumY * 8); if (!qp_av_ref) { spi_printf("Error allocating memory for loop filter average qp indices!! Exiting..."); spi_exit(-1); }#endif // The computation is strip-mined such that a strip is a // consecutive group of macroblocks all on the same row. The // StreamC code is written to process strips in vertical order, // rather than in row-major order. That is, the loop processes // the strips contain the macroblocks at macroblock coordinates // (0,0) to (N,0), then (0,1) to (N,1), etc. At this point, it // goes back to the top and process MB strips (N,0) to (2N-1,0), // then (2N,1) to (2N-1,1), and so on. (Notice the overlap of // the Nth macroblock on each row in each pair of strips). // // This overlap is needed because of the nature of the deblocking // algorithm described in the H.264 standard. In order to // conform to the standard, if the last macroblock (call it // LastStripMB) is on the right edge of the image, no special // boundary conditions need to be handled. If LastStripMB is in // the interior of the image, than only the vertical edges are // filtered for that macroblock. In this case, when the strip // next to the current one is processed (i.e., the strip that // contains the macroblocks from LastStripMB to // LastStripMB+StripSize), only the horizontal edges will be // filtered for LastStripMB. But notice that LastStripMB must be // processed by the kernel twice. This is slightly inefficient, // but if the strips are large enough (say > 25 // macroblocks/strip) this has a neglible impact on performance. // Loop over row segments (each row segment is StripSize // wide, though the last segment may be < StripSize wide) for (s = 0; s < NumStrips; s++) { // Calculate x macroblock coordinate for this strip x = s * (StripSize); // The last strip might be smaller than the rest CurrStripSize = ((x + StripSize + 1) <= MBNumX) ? (StripSize+1) : (MBNumX-x); for (y = 0 ; y < MBNumY ; y++ ) { for (m = 0; m < CurrStripSize; m++) { MBcurr = y*MBNumX + x + m; MBcurrLeft = (m == 0) ? (MBcurr) : (MBcurr - 1); MBcurrTop = (y == 0) ? (MBcurr) : (MBcurr - MBNumX); // Calculate boundary strengths for the macroblock CalcBoundaryStrength(&pBlkMBInfo[MBcurr*BLOCKS_PER_MB], &pBlkMBInfo[MBcurrLeft*BLOCKS_PER_MB], &pBlkMBInfo[MBcurrTop*BLOCKS_PER_MB], &BSRef[MBcurr], disable_deblocking_filter_idc ); // Deblock the macroblock DeblockMB(&BSRef[MBcurr], pBlkMBInfo[MBcurr*BLOCKS_PER_MB].QP, pBlkMBInfo[MBcurrLeft*BLOCKS_PER_MB].QP, pBlkMBInfo[MBcurrTop*BLOCKS_PER_MB].QP, slice_alpha_c0_offset, slice_beta_offset, frame, x + m, y, (s > 0) && (m == 0), (s < (NumStrips - 1)) && (m == (CurrStripSize - 1))); } } } pad_deblock_out_frame(p_enc->pRecFrame, REFERENCE_FRAME_PAD_AMT); // dec spi_free(BSRef);#ifdef DEBUG spi_free(qp_av_ref);#endif}//====================================================================void CalcBoundaryStrength//====================================================================// Calculate the boundary strengths for all the edges for one// Macroblock//--------------------------------------------------------------------( // Inputs S_BLK_MB_INFO *MBInfo, S_BLK_MB_INFO *MBInfoLeft, S_BLK_MB_INFO *MBInfoTop, // Output S_BOUNDARY_STRENGTH_REF *BSRef, // Inputs int disable_deblocking_filter_idc )//--------------------------------------------------------------------{ int d, i, j; // Do edges in both directions (d=0: vertical; d=1: horizontal) for (d = 0; d < 2; d++) { S_BLK_MB_INFO *NeighborBlk = ((d == 0) ? MBInfoLeft : MBInfoTop); int BlkIsIntra = ((MBInfo->Type == INTRA_LARGE_BLOCKS_MB_TYPE) || (MBInfo->Type == INTRA_SMALL_BLOCKS_MB_TYPE)); int NeighborIsIntra = ((NeighborBlk->Type == INTRA_LARGE_BLOCKS_MB_TYPE) || (NeighborBlk->Type == INTRA_SMALL_BLOCKS_MB_TYPE)); // Loop over four edges in a MB for (i = 0; i < 4; i++) { // loop over four 4x4 block positions along each edge in order // to determine strength of filtering for each group of 4 pixel // boundaries (all 4 pixel boundaries within a single 4x4 block // position all use the same strength) for (j = 0; j < 4; j++) { // indices into MV[y][x] and CBP[y][x] arrays int pXidx = ((d == 0) ? i-1 : j ); int pYidx = ((d == 0) ? j : i-1); int qXidx = ((d == 0) ? i : j ); int qYidx = ((d == 0) ? j : i ); // If this is 4x4 block is on the macroblock edge, // calculate the appropriate index into the // neighboring macroblock's 2-D array of 4x4 blocks. int NeighborX = (d == 0) ? 3 : j; int NeighborY = (d == 1) ? 3 : j; // Get p_Blk and q_Blk S_BLK_MB_INFO p_Blk = ((i == 0) ? NeighborBlk[NeighborY*4 + NeighborX] : MBInfo[pYidx*4 + pXidx]); S_BLK_MB_INFO q_Blk = MBInfo[qYidx*4 + qXidx]; // Get MVs for each 4x4 block to the left and above S_MV pMV = p_Blk.MV; S_MV qMV = q_Blk.MV; // Get Reference frames for each 4x4 block to the left and above int pRef = p_Blk.RefFrameIdx; int qRef = q_Blk.RefFrameIdx; // Check for coded coefficients in each 4x4 block to the left and above int pCodedCoeffs = (p_Blk.TotalCoeffLuma != 0); int qCodedCoeffs = (q_Blk.TotalCoeffLuma != 0); // Calculate boundary strength (bS) if ((i == 0) && (NeighborIsIntra || BlkIsIntra)) { (*BSRef)[d][i][j] = 4; } else if (BlkIsIntra) { (*BSRef)[d][i][j] = 3; } else if (pCodedCoeffs || qCodedCoeffs) { (*BSRef)[d][i][j] = 2; } else if ((pRef != qRef) || ((abs(pMV.x - qMV.x) >= 4) || (abs(pMV.y - qMV.y) >= 4))) { (*BSRef)[d][i][j] = 1; } else { (*BSRef)[d][i][j] = 0; } // check boundary conditions if ( // Check for left picture edge ((d == 0) && (i == 0) && (MBInfo->Loc & LOC_MB_LEFT_PICTURE_EDGE)) // Check for top picture edge || ((d == 1) && (i == 0) && (MBInfo->Loc & LOC_MB_TOP_PICTURE_EDGE)) // Check for disable_deblocking_filter_idc || (disable_deblocking_filter_idc == 1) // Check for slice edge || ((disable_deblocking_filter_idc == 2) && (((d == 0) && (i == 0) && (MBInfo->Loc & LOC_MB_LEFT_SLICE_EDGE)) || ((d == 1) && (i == 0) && (MBInfo->Loc & LOC_MB_TOP_SLICE_EDGE)))) ) { (*BSRef)[d][i][j] = 0; } } // for (j... } // for (i... } // for (d...}//====================================================================void DeblockMB//====================================================================// Filter (deblock) a single macroblock//--------------------------------------------------------------------( S_BOUNDARY_STRENGTH_REF *BSRef, int QPyCurr, int QPyLeft, int QPyTop, int alpha_c0_offset, int beta_offset, yuv_frame_t *frame, int MBx, int MBy, int DontFilterVertEdges, int DontFilterHorzEdges )//--------------------------------------------------------------------{ int d, i; int img_width, img_height; int buf_width, buf_height; unsigned char *y,*u, *v; buf_width = frame->width; buf_height = frame->height; img_width = frame->image_width; img_height = frame->image_height;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -