📄 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-2006 * * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: last mod: $Id: decode.c 11442 2006-05-27 17:28:08Z giles $ ********************************************************************/#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); if (ret < 0 || ret >= 64) { /* range check */ ret = 0; pbi->DecoderErrorCode = 1; } DctQIndex[NQIndex++] = (unsigned char)ret; theora_read(pbi->opb,1,&ret); SpareBits = (unsigned char)ret; if (SpareBits) { theora_read(pbi->opb,6,&ret); if (ret < 0 || ret >= 64) { /* range check */ ret = 0; pbi->DecoderErrorCode = 1; } DctQIndex[NQIndex++] = (unsigned char)ret; theora_read(pbi->opb,1,&ret); SpareBits = (unsigned char)ret; if (SpareBits) { theora_read(pbi->opb,6,&ret); if (ret < 0 || ret >= 64) { /* range check */ ret = 0; pbi->DecoderErrorCode = 1; } 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 pbi->DecoderErrorCode;}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) == 0 ){ /* Read in the updated block map */ QuadDecodeDisplayFragments( pbi ); return 0; } return pbi->DecoderErrorCode;}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; default: /* occurs if there is a read error */ MVectComponent = 0; } 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 vectors to 0,0 */ MVect[0].x = 0; MVect[0].y = 0; MVect[1].x = 0; MVect[1].y = 0; MVect[2].x = 0; MVect[2].y = 0; MVect[3].x = 0; MVect[3].y = 0; MVect[4].x = 0; MVect[4].y = 0; MVect[5].x = 0; MVect[5].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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -