📄 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:
********************************************************************/
#include <stdlib.h>
#include <string.h>
#include "codec_internal.h"
#include "dsp.h"
#include <mmintrin.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
};
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 };
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;
}
pbi->BoundingValuePtr=BoundingValuePtr;
}
/* 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];
dsp_funcs.SetupBoundingValueArray(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:
dsp_funcs.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:
dsp_funcs.IDct10( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
break;
default:
dsp_funcs.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_static_recon_intra8x8 ((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:
dsp_funcs.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:
dsp_funcs.IDct10( pbi->quantized_list, pbi->dequant_coeffs, pbi->ReconDataBuffer );
break;
default:
dsp_funcs.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_static_recon_inter8x8 (&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_static_recon_inter8x8 (
&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_static_recon_inter8x8_half(&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_static_recon_inter8x8 (&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_static_recon_intra8x8 (&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] +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -