📄 dct_decode.c
字号:
/******************************************************************** * * * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2003 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: last mod: $Id: dct_decode.c 11442 2006-05-27 17:28:08Z giles $ ********************************************************************/#include <stdlib.h>#include <string.h>#include "codec_internal.h"#include "dsp.h"#define GOLDEN_FRAME_THRESH_Q 50#define PUR 8#define PU 4#define PUL 2#define PL 1#define HIGHBITDUPPED(X) (((signed short) X) >> 15)/* in-loop filter tables. one of these is used in dct_decode.c */static const unsigned char LoopFilterLimitValuesV1[Q_TABLE_SIZE] = { 30, 25, 20, 20, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};static const unsigned char LoopFilterLimitValuesV2[Q_TABLE_SIZE] = { 30, 25, 20, 20, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1};static const int ModeUsesMC[MAX_MODES] = { 0, 0, 1, 1, 1, 0, 1, 1 };static void SetupBoundingValueArray_Generic(PB_INSTANCE *pbi, ogg_int32_t FLimit){ ogg_int32_t * BoundingValuePtr = pbi->FiltBoundingValue+256; ogg_int32_t i; /* Set up the bounding value array. */ memset ( pbi->FiltBoundingValue, 0, (512*sizeof(*pbi->FiltBoundingValue)) ); for ( i = 0; i < FLimit; i++ ){ BoundingValuePtr[-i-FLimit] = (-FLimit+i); BoundingValuePtr[-i] = -i; BoundingValuePtr[i] = i; BoundingValuePtr[i+FLimit] = FLimit-i; }}/* handle the in-loop filter limit value table */void WriteFilterTables(PB_INSTANCE *pbi, oggpack_buffer *opb){ int i; int bits=5; oggpackB_write(opb, bits, 3); for(i=0;i<Q_TABLE_SIZE;i++) oggpackB_write(opb, pbi->LoopFilterLimits[i],bits);}int ReadFilterTables(codec_setup_info *ci, oggpack_buffer *opb){ int i; int bits, value; theora_read(opb, 3, &bits); for(i=0;i<Q_TABLE_SIZE;i++){ theora_read(opb,bits,&value); ci->LoopFilterLimitValues[i]=value; } if(bits<0)return OC_BADHEADER; return 0;}/* copy in-loop filter limits from the bitstream header into our instance */void CopyFilterTables(PB_INSTANCE *pbi, codec_setup_info *ci){ memcpy(pbi->LoopFilterLimits, ci->LoopFilterLimitValues, Q_TABLE_SIZE);}/* initialize the filter limits from our static table */void InitFilterTables(PB_INSTANCE *pbi){ memcpy(pbi->LoopFilterLimits, LoopFilterLimitValuesV1, Q_TABLE_SIZE);}void SetupLoopFilter(PB_INSTANCE *pbi){ ogg_int32_t FLimit; /* nb: this was using the V2 values rather than V1 we think is was a mistake; the results were not used */ FLimit = pbi->LoopFilterLimits[pbi->FrameQIndex]; SetupBoundingValueArray_Generic(pbi, FLimit);}static void ExpandKFBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){ ogg_uint32_t ReconPixelsPerLine; ogg_int32_t ReconPixelIndex; /* Select the appropriate inverse Q matrix and line stride */ if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ){ ReconPixelsPerLine = pbi->YStride; pbi->dequant_coeffs = pbi->dequant_Y_coeffs; }else if ( FragmentNumber<(ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ){ ReconPixelsPerLine = pbi->UVStride; pbi->dequant_coeffs = pbi->dequant_U_coeffs; }else{ ReconPixelsPerLine = pbi->UVStride; pbi->dequant_coeffs = pbi->dequant_V_coeffs; } /* Set up pointer into the quantisation buffer. */ pbi->quantized_list = &pbi->QFragData[FragmentNumber][0]; /* Invert quantisation and DCT to get pixel data. */ switch(pbi->FragCoefEOB[FragmentNumber]){ case 0:case 1: IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); break; case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10: IDct10( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); break; default: IDctSlow( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); } /* Convert fragment number to a pixel offset in a reconstruction buffer. */ ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber]; /* Get the pixel index for the first pixel in the fragment. */ dsp_recon_intra8x8 (pbi->dsp, (unsigned char *)(&pbi->ThisFrameRecon[ReconPixelIndex]), (ogg_int16_t *)pbi->ReconDataBuffer, ReconPixelsPerLine);}static void ExpandBlock ( PB_INSTANCE *pbi, ogg_int32_t FragmentNumber ){ unsigned char *LastFrameRecPtr; /* Pointer into previous frame reconstruction. */ unsigned char *LastFrameRecPtr2; /* Pointer into previous frame reconstruction for 1/2 pixel MC. */ ogg_uint32_t ReconPixelsPerLine; /* Pixels per line */ ogg_int32_t ReconPixelIndex; /* Offset for block into a reconstruction buffer */ ogg_int32_t ReconPtr2Offset; /* Offset for second reconstruction in half pixel MC */ ogg_int32_t MVOffset; /* Baseline motion vector offset */ ogg_int32_t MvShift ; /* Shift to correct to 1/2 or 1/4 pixel */ ogg_int32_t MvModMask; /* Mask to determine whether 1/2 pixel is used */ /* Get coding mode for this block */ if ( GetFrameType(pbi) == KEY_FRAME ){ pbi->CodingMode = CODE_INTRA; }else{ /* Get Motion vector and mode for this block. */ pbi->CodingMode = pbi->FragCodingMethod[FragmentNumber]; } /* Select the appropriate inverse Q matrix and line stride */ if ( FragmentNumber<(ogg_int32_t)pbi->YPlaneFragments ) { ReconPixelsPerLine = pbi->YStride; MvShift = 1; MvModMask = 0x00000001; /* Select appropriate dequantiser matrix. */ if ( pbi->CodingMode == CODE_INTRA ) pbi->dequant_coeffs = pbi->dequant_Y_coeffs; else pbi->dequant_coeffs = pbi->dequant_InterY_coeffs; }else{ ReconPixelsPerLine = pbi->UVStride; MvShift = 2; MvModMask = 0x00000003; /* Select appropriate dequantiser matrix. */ if ( pbi->CodingMode == CODE_INTRA ) if ( FragmentNumber < (ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ) pbi->dequant_coeffs = pbi->dequant_U_coeffs; else pbi->dequant_coeffs = pbi->dequant_V_coeffs; else if ( FragmentNumber < (ogg_int32_t)(pbi->YPlaneFragments + pbi->UVPlaneFragments) ) pbi->dequant_coeffs = pbi->dequant_InterU_coeffs; else pbi->dequant_coeffs = pbi->dequant_InterV_coeffs; } /* Set up pointer into the quantisation buffer. */ pbi->quantized_list = &pbi->QFragData[FragmentNumber][0]; /* Invert quantisation and DCT to get pixel data. */ switch(pbi->FragCoefEOB[FragmentNumber]){ case 0:case 1: IDct1( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); break; case 2: case 3:case 4:case 5:case 6:case 7:case 8: case 9:case 10: IDct10( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); break; default: IDctSlow( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer ); } /* Convert fragment number to a pixel offset in a reconstruction buffer. */ ReconPixelIndex = pbi->recon_pixel_index_table[FragmentNumber]; /* Action depends on decode mode. */ if ( pbi->CodingMode == CODE_INTER_NO_MV ){ /* Inter with no motion vector */ /* Reconstruct the pixel data using the last frame reconstruction and change data when the motion vector is (0,0), the recon is based on the lastframe without loop filtering---- for testing */ dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], &pbi->LastFrameRecon[ReconPixelIndex], pbi->ReconDataBuffer, ReconPixelsPerLine); }else if ( ModeUsesMC[pbi->CodingMode] ) { /* The mode uses a motion vector. */ /* Get vector from list */ pbi->MVector.x = pbi->FragMVect[FragmentNumber].x; pbi->MVector.y = pbi->FragMVect[FragmentNumber].y; /* Work out the base motion vector offset and the 1/2 pixel offset if any. For the U and V planes the MV specifies 1/4 pixel accuracy. This is adjusted to 1/2 pixel as follows ( 0->0, 1/4->1/2, 1/2->1/2, 3/4->1/2 ). */ MVOffset = 0; ReconPtr2Offset = 0; if ( pbi->MVector.x > 0 ){ MVOffset = pbi->MVector.x >> MvShift; if ( pbi->MVector.x & MvModMask ) ReconPtr2Offset += 1; } else if ( pbi->MVector.x < 0 ) { MVOffset -= (-pbi->MVector.x) >> MvShift; if ( (-pbi->MVector.x) & MvModMask ) ReconPtr2Offset -= 1; } if ( pbi->MVector.y > 0 ){ MVOffset += (pbi->MVector.y >> MvShift) * ReconPixelsPerLine; if ( pbi->MVector.y & MvModMask ) ReconPtr2Offset += ReconPixelsPerLine; } else if ( pbi->MVector.y < 0 ){ MVOffset -= ((-pbi->MVector.y) >> MvShift) * ReconPixelsPerLine; if ( (-pbi->MVector.y) & MvModMask ) ReconPtr2Offset -= ReconPixelsPerLine; } /* Set up the first of the two reconstruction buffer pointers. */ if ( pbi->CodingMode==CODE_GOLDEN_MV ) { LastFrameRecPtr = &pbi->GoldenFrame[ReconPixelIndex] + MVOffset; }else{ LastFrameRecPtr = &pbi->LastFrameRecon[ReconPixelIndex] + MVOffset; } /* Set up the second of the two reconstruction pointers. */ LastFrameRecPtr2 = LastFrameRecPtr + ReconPtr2Offset; /* Select the appropriate reconstruction function */ if ( (int)(LastFrameRecPtr - LastFrameRecPtr2) == 0 ) { /* Reconstruct the pixel dats from the reference frame and change data (no half pixel in this case as the two references were the same. */ dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], LastFrameRecPtr, pbi->ReconDataBuffer, ReconPixelsPerLine); }else{ /* Fractional pixel reconstruction. */ /* Note that we only use two pixels per reconstruction even for the diagonal. */ dsp_recon_inter8x8_half(pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], LastFrameRecPtr, LastFrameRecPtr2, pbi->ReconDataBuffer, ReconPixelsPerLine); } } else if ( pbi->CodingMode == CODE_USING_GOLDEN ){ /* Golden frame with motion vector */ /* Reconstruct the pixel data using the golden frame reconstruction and change data */ dsp_recon_inter8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], &pbi->GoldenFrame[ ReconPixelIndex ], pbi->ReconDataBuffer, ReconPixelsPerLine); } else { /* Simple Intra coding */ /* Get the pixel index for the first pixel in the fragment. */ dsp_recon_intra8x8 (pbi->dsp, &pbi->ThisFrameRecon[ReconPixelIndex], pbi->ReconDataBuffer, ReconPixelsPerLine); }}static void UpdateUMV_HBorders( PB_INSTANCE *pbi, unsigned char * DestReconPtr, ogg_uint32_t PlaneFragOffset ) { ogg_uint32_t i; ogg_uint32_t PixelIndex; ogg_uint32_t PlaneStride; ogg_uint32_t BlockVStep; ogg_uint32_t PlaneFragments; ogg_uint32_t LineFragments; ogg_uint32_t PlaneBorderWidth; unsigned char *SrcPtr1; unsigned char *SrcPtr2; unsigned char *DestPtr1; unsigned char *DestPtr2; /* Work out various plane specific values */ if ( PlaneFragOffset == 0 ) { /* Y Plane */ BlockVStep = (pbi->YStride * (VFRAGPIXELS - 1)); PlaneStride = pbi->YStride; PlaneBorderWidth = UMV_BORDER; PlaneFragments = pbi->YPlaneFragments; LineFragments = pbi->HFragments; }else{ /* U or V plane. */ BlockVStep = (pbi->UVStride * (VFRAGPIXELS - 1)); PlaneStride = pbi->UVStride; PlaneBorderWidth = UMV_BORDER / 2; PlaneFragments = pbi->UVPlaneFragments; LineFragments = pbi->HFragments / 2; } /* Setup the source and destination pointers for the top and bottom borders */ PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset]; SrcPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ]; DestPtr1 = SrcPtr1 - (PlaneBorderWidth * PlaneStride); PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset + PlaneFragments - LineFragments] + BlockVStep; SrcPtr2 = &DestReconPtr[ PixelIndex - PlaneBorderWidth]; DestPtr2 = SrcPtr2 + PlaneStride; /* Now copy the top and bottom source lines into each line of the respective borders */ for ( i = 0; i < PlaneBorderWidth; i++ ) { memcpy( DestPtr1, SrcPtr1, PlaneStride ); memcpy( DestPtr2, SrcPtr2, PlaneStride ); DestPtr1 += PlaneStride; DestPtr2 += PlaneStride; }}static void UpdateUMV_VBorders( PB_INSTANCE *pbi, unsigned char * DestReconPtr, ogg_uint32_t PlaneFragOffset ){ ogg_uint32_t i; ogg_uint32_t PixelIndex; ogg_uint32_t PlaneStride; ogg_uint32_t LineFragments; ogg_uint32_t PlaneBorderWidth; ogg_uint32_t PlaneHeight; unsigned char *SrcPtr1; unsigned char *SrcPtr2; unsigned char *DestPtr1; unsigned char *DestPtr2; /* Work out various plane specific values */ if ( PlaneFragOffset == 0 ) { /* Y Plane */ PlaneStride = pbi->YStride; PlaneBorderWidth = UMV_BORDER; LineFragments = pbi->HFragments; PlaneHeight = pbi->info.height; }else{ /* U or V plane. */ PlaneStride = pbi->UVStride; PlaneBorderWidth = UMV_BORDER / 2; LineFragments = pbi->HFragments / 2; PlaneHeight = pbi->info.height / 2; } /* Setup the source data values and destination pointers for the left and right edge borders */ PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset]; SrcPtr1 = &DestReconPtr[ PixelIndex ]; DestPtr1 = &DestReconPtr[ PixelIndex - PlaneBorderWidth ]; PixelIndex = pbi->recon_pixel_index_table[PlaneFragOffset + LineFragments - 1] + (HFRAGPIXELS - 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -