📄 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 <string.h>
#include "codec_internal.h"
#include "block_inline.h"
static const CODING_MODE ModeAlphabet[MODE_METHODS-2][MAX_MODES] = {
/* Last motion vector dominates */
{ CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST,
CODE_INTER_PLUS_MV, CODE_INTER_NO_MV,
CODE_INTRA, CODE_USING_GOLDEN,
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
{ CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST,
CODE_INTER_NO_MV, CODE_INTER_PLUS_MV,
CODE_INTRA, CODE_USING_GOLDEN,
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
{ CODE_INTER_LAST_MV, CODE_INTER_PLUS_MV,
CODE_INTER_PRIOR_LAST, CODE_INTER_NO_MV,
CODE_INTRA, CODE_USING_GOLDEN,
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
{ CODE_INTER_LAST_MV, CODE_INTER_PLUS_MV,
CODE_INTER_NO_MV, CODE_INTER_PRIOR_LAST,
CODE_INTRA, CODE_USING_GOLDEN,
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
/* No motion vector dominates */
{ CODE_INTER_NO_MV, CODE_INTER_LAST_MV,
CODE_INTER_PRIOR_LAST, CODE_INTER_PLUS_MV,
CODE_INTRA, CODE_USING_GOLDEN,
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
{ CODE_INTER_NO_MV, CODE_USING_GOLDEN,
CODE_INTER_LAST_MV, CODE_INTER_PRIOR_LAST,
CODE_INTER_PLUS_MV, CODE_INTRA,
CODE_GOLDEN_MV, CODE_INTER_FOURMV },
};
int GetFrameType(PB_INSTANCE *pbi){
return pbi->FrameType;
}
static int LoadFrameHeader(PB_INSTANCE *pbi){
long ret;
int NQIndex;
unsigned char DctQIndex[3];
unsigned char SpareBits; /* Spare cfg bits */
/* Is the frame and inter frame or a key frame */
theora_read(pbi->opb,1,&ret);
pbi->FrameType = (unsigned char)ret;
/* Quality (Q) index */
NQIndex = 0;
theora_read(pbi->opb,6,&ret);
DctQIndex[NQIndex++] = (unsigned char)ret;
theora_read(pbi->opb,1,&ret);
SpareBits = (unsigned char)ret;
if (SpareBits) {
theora_read(pbi->opb,6,&ret);
DctQIndex[NQIndex++] = (unsigned char)ret;
theora_read(pbi->opb,1,&ret);
SpareBits = (unsigned char)ret;
if (SpareBits) {
theora_read(pbi->opb,6,&ret);
DctQIndex[NQIndex++] = (unsigned char)ret;
}
}
if (NQIndex != 1) return OC_IMPL;
if ( (pbi->FrameType == KEY_FRAME) ){
/* Read the type / coding method for the key frame. */
theora_read(pbi->opb,1,&ret);
pbi->KeyFrameType = (unsigned char)ret;
theora_read(pbi->opb,2,&ret);
SpareBits = (unsigned char)ret;
if (pbi->KeyFrameType || SpareBits) return OC_BADPACKET;
}
/* Set this frame quality value and tables from the coded Q Index */
UpdateQ(pbi, DctQIndex[0]);
return 1;
}
void SetFrameType( PB_INSTANCE *pbi,unsigned char FrType ){
/* Set the appropriate frame type according to the request. */
switch ( FrType ){
case KEY_FRAME:
pbi->FrameType = FrType;
break;
default:
pbi->FrameType = FrType;
break;
}
}
static int LoadFrame(PB_INSTANCE *pbi){
/* Load the frame header (including the frame size). */
if ( LoadFrameHeader(pbi) ){
/* Read in the updated block map */
QuadDecodeDisplayFragments( pbi );
return 1;
}
return 0;
}
static void DecodeModes (PB_INSTANCE *pbi,
ogg_uint32_t SBRows,
ogg_uint32_t SBCols){
long ret;
ogg_int32_t FragIndex;
ogg_uint32_t MB;
ogg_uint32_t SBrow;
ogg_uint32_t SBcol;
ogg_uint32_t SB=0;
CODING_MODE CodingMethod;
ogg_uint32_t UVRow;
ogg_uint32_t UVColumn;
ogg_uint32_t UVFragOffset;
ogg_uint32_t CodingScheme;
ogg_uint32_t MBListIndex = 0;
ogg_uint32_t i;
/* If the frame is an intra frame then all blocks have mode intra. */
if ( GetFrameType(pbi) == KEY_FRAME ){
for ( i = 0; i < pbi->UnitFragments; i++ ){
pbi->FragCodingMethod[i] = CODE_INTRA;
}
}else{
ogg_uint32_t ModeEntry; /* Mode bits read */
CODING_MODE CustomModeAlphabet[MAX_MODES];
const CODING_MODE *ModeList;
/* Read the coding method */
theora_read(pbi->opb, MODE_METHOD_BITS, &ret);
CodingScheme=ret;
/* If the coding method is method 0 then we have to read in a
custom coding scheme */
if ( CodingScheme == 0 ){
/* Read the coding scheme. */
for ( i = 0; i < MAX_MODES; i++ ){
theora_read(pbi->opb, MODE_BITS, &ret);
CustomModeAlphabet[ret]=i;
}
ModeList=CustomModeAlphabet;
}
else{
ModeList=ModeAlphabet[CodingScheme-1];
}
/* Unravel the quad-tree */
for ( SBrow=0; SBrow<SBRows; SBrow++ ){
for ( SBcol=0; SBcol<SBCols; SBcol++ ){
for ( MB=0; MB<4; MB++ ){
/* There may be MB's lying out of frame which must be
ignored. For these MB's top left block will have a negative
Fragment Index. */
if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0){
/* Is the Macro-Block coded: */
if ( pbi->MBCodedFlags[MBListIndex++] ){
/* Upack the block level modes and motion vectors */
FragIndex = QuadMapToMBTopLeft( pbi->BlockMap, SB, MB );
/* Unpack the mode. */
if ( CodingScheme == (MODE_METHODS-1) ){
/* This is the fall back coding scheme. */
/* Simply MODE_BITS bits per mode entry. */
theora_read(pbi->opb, MODE_BITS, &ret);
CodingMethod = (CODING_MODE)ret;
}else{
ModeEntry = FrArrayUnpackMode(pbi);
CodingMethod = ModeList[ModeEntry];
}
/* Note the coding mode for each block in macro block. */
pbi->FragCodingMethod[FragIndex] = CodingMethod;
pbi->FragCodingMethod[FragIndex + 1] = CodingMethod;
pbi->FragCodingMethod[FragIndex + pbi->HFragments] =
CodingMethod;
pbi->FragCodingMethod[FragIndex + pbi->HFragments + 1] =
CodingMethod;
/* Matching fragments in the U and V planes */
UVRow = (FragIndex / (pbi->HFragments * 2));
UVColumn = (FragIndex % pbi->HFragments) / 2;
UVFragOffset = (UVRow * (pbi->HFragments / 2)) + UVColumn;
pbi->FragCodingMethod[pbi->YPlaneFragments + UVFragOffset] =
CodingMethod;
pbi->FragCodingMethod[pbi->YPlaneFragments +
pbi->UVPlaneFragments + UVFragOffset] =
CodingMethod;
}
}
}
/* Next Super-Block */
SB++;
}
}
}
}
static ogg_int32_t ExtractMVectorComponentA(PB_INSTANCE *pbi){
long ret;
ogg_int32_t MVectComponent;
ogg_uint32_t MVCode = 0;
ogg_uint32_t ExtraBits = 0;
/* Get group to which coded component belongs */
theora_read(pbi->opb, 3, &ret);
MVCode=ret;
/* Now extract the appropriate number of bits to identify the component */
switch ( MVCode ){
case 0:
MVectComponent = 0;
break;
case 1:
MVectComponent = 1;
break;
case 2:
MVectComponent = -1;
break;
case 3:
theora_read(pbi->opb,1,&ret);
if (ret)
MVectComponent = -2;
else
MVectComponent = 2;
break;
case 4:
theora_read(pbi->opb,1,&ret);
if (ret)
MVectComponent = -3;
else
MVectComponent = 3;
break;
case 5:
theora_read(pbi->opb,2,&ret);
ExtraBits=ret;
MVectComponent = 4 + ExtraBits;
theora_read(pbi->opb,1,&ret);
if (ret)
MVectComponent = -MVectComponent;
break;
case 6:
theora_read(pbi->opb,3,&ret);
ExtraBits=ret;
MVectComponent = 8 + ExtraBits;
theora_read(pbi->opb,1,&ret);
if (ret)
MVectComponent = -MVectComponent;
break;
case 7:
theora_read(pbi->opb,4,&ret);
ExtraBits=ret;
MVectComponent = 16 + ExtraBits;
theora_read(pbi->opb,1,&ret);
if (ret)
MVectComponent = -MVectComponent;
break;
}
return MVectComponent;
}
static ogg_int32_t ExtractMVectorComponentB(PB_INSTANCE *pbi){
long ret;
ogg_int32_t MVectComponent;
/* Get group to which coded component belongs */
theora_read(pbi->opb,5,&ret);
MVectComponent=ret;
theora_read(pbi->opb,1,&ret);
if (ret)
MVectComponent = -MVectComponent;
return MVectComponent;
}
static void DecodeMVectors ( PB_INSTANCE *pbi,
ogg_uint32_t SBRows,
ogg_uint32_t SBCols ){
long ret;
ogg_int32_t FragIndex;
ogg_uint32_t MB;
ogg_uint32_t SBrow;
ogg_uint32_t SBcol;
ogg_uint32_t SB=0;
ogg_uint32_t CodingMethod;
MOTION_VECTOR MVect[6];
MOTION_VECTOR TmpMVect;
MOTION_VECTOR LastInterMV;
MOTION_VECTOR PriorLastInterMV;
ogg_int32_t (*ExtractMVectorComponent)(PB_INSTANCE *pbi);
ogg_uint32_t UVRow;
ogg_uint32_t UVColumn;
ogg_uint32_t UVFragOffset;
ogg_uint32_t MBListIndex = 0;
/* Should not be decoding motion vectors if in INTRA only mode. */
if ( GetFrameType(pbi) == KEY_FRAME ){
return;
}
/* set the default motion vector to 0,0 */
MVect[0].x = 0;
MVect[0].y = 0;
LastInterMV.x = 0;
LastInterMV.y = 0;
PriorLastInterMV.x = 0;
PriorLastInterMV.y = 0;
/* Read the entropy method used and set up the appropriate decode option */
theora_read(pbi->opb, 1, &ret);
if ( ret == 0 )
ExtractMVectorComponent = ExtractMVectorComponentA;
else
ExtractMVectorComponent = ExtractMVectorComponentB;
/* Unravel the quad-tree */
for ( SBrow=0; SBrow<SBRows; SBrow++ ){
for ( SBcol=0; SBcol<SBCols; SBcol++ ){
for ( MB=0; MB<4; MB++ ){
/* There may be MB's lying out of frame which must be
ignored. For these MB's the top left block will have a
negative Fragment. */
if ( QuadMapToMBTopLeft(pbi->BlockMap, SB,MB) >= 0 ) {
/* Is the Macro-Block further coded: */
if ( pbi->MBCodedFlags[MBListIndex++] ){
/* Upack the block level modes and motion vectors */
FragIndex = QuadMapToMBTopLeft( pbi->BlockMap, SB, MB );
/* Clear the motion vector before we start. */
MVect[0].x = 0;
MVect[0].y = 0;
/* Unpack the mode (and motion vectors if necessary). */
CodingMethod = pbi->FragCodingMethod[FragIndex];
/* Read the motion vector or vectors if present. */
if ( (CodingMethod == CODE_INTER_PLUS_MV) ||
(CodingMethod == CODE_GOLDEN_MV) ){
MVect[0].x = ExtractMVectorComponent(pbi);
MVect[1].x = MVect[0].x;
MVect[2].x = MVect[0].x;
MVect[3].x = MVect[0].x;
MVect[4].x = MVect[0].x;
MVect[5].x = MVect[0].x;
MVect[0].y = ExtractMVectorComponent(pbi);
MVect[1].y = MVect[0].y;
MVect[2].y = MVect[0].y;
MVect[3].y = MVect[0].y;
MVect[4].y = MVect[0].y;
MVect[5].y = MVect[0].y;
}else if ( CodingMethod == CODE_INTER_FOURMV ){
/* Extrac the 4 Y MVs */
MVect[0].x = ExtractMVectorComponent(pbi);
MVect[0].y = ExtractMVectorComponent(pbi);
MVect[1].x = ExtractMVectorComponent(pbi);
MVect[1].y = ExtractMVectorComponent(pbi);
MVect[2].x = ExtractMVectorComponent(pbi);
MVect[2].y = ExtractMVectorComponent(pbi);
MVect[3].x = ExtractMVectorComponent(pbi);
MVect[3].y = ExtractMVectorComponent(pbi);
/* Calculate the U and V plane MVs as the average of the
Y plane MVs. */
/* First .x component */
MVect[4].x = MVect[0].x + MVect[1].x + MVect[2].x + MVect[3].x;
if ( MVect[4].x >= 0 )
MVect[4].x = (MVect[4].x + 2) / 4;
else
MVect[4].x = (MVect[4].x - 2) / 4;
MVect[5].x = MVect[4].x;
/* Then .y component */
MVect[4].y = MVect[0].y + MVect[1].y + MVect[2].y + MVect[3].y;
if ( MVect[4].y >= 0 )
MVect[4].y = (MVect[4].y + 2) / 4;
else
MVect[4].y = (MVect[4].y - 2) / 4;
MVect[5].y = MVect[4].y;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -