📄 encode.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: encode.c 11442 2006-05-27 17:28:08Z giles $ ********************************************************************/#include <stdlib.h>#include <string.h>#include "codec_internal.h"#include "encoder_lookup.h"#include "block_inline.h"#define PUR 8#define PU 4#define PUL 2#define PL 1#define HIGHBITDUPPED(X) (((ogg_int16_t) X) >> 15)static ogg_uint32_t QuadCodeComponent ( CP_INSTANCE *cpi, ogg_uint32_t FirstSB, ogg_uint32_t SBRows, ogg_uint32_t SBCols, ogg_uint32_t PixelsPerLine ){ ogg_int32_t FragIndex; /* Fragment number */ ogg_uint32_t MB, B; /* Macro-Block, Block indices */ ogg_uint32_t SBrow; /* Super-Block row number */ ogg_uint32_t SBcol; /* Super-Block row number */ ogg_uint32_t SB=FirstSB; /* Super-Block index, initialised to first of this component */ ogg_uint32_t coded_pixels=0; /* Number of pixels coded */ int MBCodedFlag; /* actually transform and quantize the image now that we've decided on the modes Parse in quad-tree ordering */ SB=FirstSB; for ( SBrow=0; SBrow<SBRows; SBrow++ ) { for ( SBcol=0; SBcol<SBCols; SBcol++ ) { /* Check its four Macro-Blocks */ for ( MB=0; MB<4; MB++ ) { if ( QuadMapToMBTopLeft(cpi->pb.BlockMap,SB,MB) >= 0 ) { MBCodedFlag = 0; /* Now actually code the blocks */ for ( B=0; B<4; B++ ) { FragIndex = QuadMapToIndex1( cpi->pb.BlockMap, SB, MB, B ); /* Does Block lie in frame: */ if ( FragIndex >= 0 ) { /* In Frame: Is it coded: */ if ( cpi->pb.display_fragments[FragIndex] ) { /* transform and quantize block */ TransformQuantizeBlock( cpi, FragIndex, PixelsPerLine ); /* Has the block got struck off (no MV and no data generated after DCT) If not then mark it and the assosciated MB as coded. */ if ( cpi->pb.display_fragments[FragIndex] ) { /* Create linear list of coded block indices */ cpi->pb.CodedBlockList[cpi->pb.CodedBlockIndex] = FragIndex; cpi->pb.CodedBlockIndex++; /* MB is still coded */ MBCodedFlag = 1; cpi->MBCodingMode = cpi->pb.FragCodingMethod[FragIndex]; } } } } /* If the MB is marked as coded and we are in the Y plane then */ /* the mode list needs to be updated. */ if ( MBCodedFlag && (FirstSB == 0) ){ /* Make a note of the selected mode in the mode list */ cpi->ModeList[cpi->ModeListCount] = cpi->MBCodingMode; cpi->ModeListCount++; } } } SB++; } } /* Return number of pixels coded */ return coded_pixels;}static void EncodeDcTokenList (CP_INSTANCE *cpi) { ogg_int32_t i,j; ogg_uint32_t Token; ogg_uint32_t ExtraBitsToken; ogg_uint32_t HuffIndex; ogg_uint32_t BestDcBits; ogg_uint32_t DcHuffChoice[2]; ogg_uint32_t EntropyTableBits[2][DC_HUFF_CHOICES]; oggpack_buffer *opb=cpi->oggbuffer; /* Clear table data structure */ memset ( EntropyTableBits, 0, sizeof(ogg_uint32_t)*DC_HUFF_CHOICES*2 ); /* Analyse token list to see which is the best entropy table to use */ for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { /* Count number of bits for each table option */ Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; for ( j = 0; j < DC_HUFF_CHOICES; j++ ){ EntropyTableBits[cpi->OptimisedTokenListPl[i]][j] += cpi->pb.HuffCodeLengthArray_VP3x[DC_HUFF_OFFSET + j][Token]; } } /* Work out which table option is best for Y */ BestDcBits = EntropyTableBits[0][0]; DcHuffChoice[0] = 0; for ( j = 1; j < DC_HUFF_CHOICES; j++ ) { if ( EntropyTableBits[0][j] < BestDcBits ) { BestDcBits = EntropyTableBits[0][j]; DcHuffChoice[0] = j; } } /* Add the DC huffman table choice to the bitstream */ oggpackB_write( opb, DcHuffChoice[0], DC_HUFF_CHOICE_BITS ); /* Work out which table option is best for UV */ BestDcBits = EntropyTableBits[1][0]; DcHuffChoice[1] = 0; for ( j = 1; j < DC_HUFF_CHOICES; j++ ) { if ( EntropyTableBits[1][j] < BestDcBits ) { BestDcBits = EntropyTableBits[1][j]; DcHuffChoice[1] = j; } } /* Add the DC huffman table choice to the bitstream */ oggpackB_write( opb, DcHuffChoice[1], DC_HUFF_CHOICE_BITS ); /* Encode the token list */ for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { /* Get the token and extra bits */ Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; ExtraBitsToken = (ogg_uint32_t)cpi->OptimisedTokenListEb[i]; /* Select the huffman table */ if ( cpi->OptimisedTokenListPl[i] == 0) HuffIndex = (ogg_uint32_t)DC_HUFF_OFFSET + (ogg_uint32_t)DcHuffChoice[0]; else HuffIndex = (ogg_uint32_t)DC_HUFF_OFFSET + (ogg_uint32_t)DcHuffChoice[1]; /* Add the bits to the encode holding buffer. */ cpi->FrameBitCount += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex][Token]; oggpackB_write( opb, cpi->pb.HuffCodeArray_VP3x[HuffIndex][Token], (ogg_uint32_t)cpi-> pb.HuffCodeLengthArray_VP3x[HuffIndex][Token] ); /* If the token is followed by an extra bits token then code it */ if ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ) { /* Add the bits to the encode holding buffer. */ cpi->FrameBitCount += cpi->pb.ExtraBitLengths_VP3x[Token]; oggpackB_write( opb, ExtraBitsToken, (ogg_uint32_t)cpi->pb.ExtraBitLengths_VP3x[Token] ); } } /* Reset the count of second order optimised tokens */ cpi->OptimisedTokenCount = 0;}static void EncodeAcTokenList (CP_INSTANCE *cpi) { ogg_int32_t i,j; ogg_uint32_t Token; ogg_uint32_t ExtraBitsToken; ogg_uint32_t HuffIndex; ogg_uint32_t BestAcBits; ogg_uint32_t AcHuffChoice[2]; ogg_uint32_t EntropyTableBits[2][AC_HUFF_CHOICES]; oggpack_buffer *opb=cpi->oggbuffer; memset ( EntropyTableBits, 0, sizeof(ogg_uint32_t)*AC_HUFF_CHOICES*2 ); /* Analyse token list to see which is the best entropy table to use */ for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { /* Count number of bits for each table option */ Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; HuffIndex = cpi->OptimisedTokenListHi[i]; for ( j = 0; j < AC_HUFF_CHOICES; j++ ) { EntropyTableBits[cpi->OptimisedTokenListPl[i]][j] += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex + j][Token]; } } /* Select the best set of AC tables for Y */ BestAcBits = EntropyTableBits[0][0]; AcHuffChoice[0] = 0; for ( j = 1; j < AC_HUFF_CHOICES; j++ ) { if ( EntropyTableBits[0][j] < BestAcBits ) { BestAcBits = EntropyTableBits[0][j]; AcHuffChoice[0] = j; } } /* Add the AC-Y huffman table choice to the bitstream */ oggpackB_write( opb, AcHuffChoice[0], AC_HUFF_CHOICE_BITS ); /* Select the best set of AC tables for UV */ BestAcBits = EntropyTableBits[1][0]; AcHuffChoice[1] = 0; for ( j = 1; j < AC_HUFF_CHOICES; j++ ) { if ( EntropyTableBits[1][j] < BestAcBits ) { BestAcBits = EntropyTableBits[1][j]; AcHuffChoice[1] = j; } } /* Add the AC-UV huffman table choice to the bitstream */ oggpackB_write( opb, AcHuffChoice[1], AC_HUFF_CHOICE_BITS ); /* Encode the token list */ for ( i = 0; i < cpi->OptimisedTokenCount; i++ ) { /* Get the token and extra bits */ Token = (ogg_uint32_t)cpi->OptimisedTokenList[i]; ExtraBitsToken = (ogg_uint32_t)cpi->OptimisedTokenListEb[i]; /* Select the huffman table */ HuffIndex = (ogg_uint32_t)cpi->OptimisedTokenListHi[i] + AcHuffChoice[cpi->OptimisedTokenListPl[i]]; /* Add the bits to the encode holding buffer. */ cpi->FrameBitCount += cpi->pb.HuffCodeLengthArray_VP3x[HuffIndex][Token]; oggpackB_write( opb, cpi->pb.HuffCodeArray_VP3x[HuffIndex][Token], (ogg_uint32_t)cpi-> pb.HuffCodeLengthArray_VP3x[HuffIndex][Token] ); /* If the token is followed by an extra bits token then code it */ if ( cpi->pb.ExtraBitLengths_VP3x[Token] > 0 ) { /* Add the bits to the encode holding buffer. */ cpi->FrameBitCount += cpi->pb.ExtraBitLengths_VP3x[Token]; oggpackB_write( opb, ExtraBitsToken, (ogg_uint32_t)cpi->pb.ExtraBitLengths_VP3x[Token] ); } } /* Reset the count of second order optimised tokens */ cpi->OptimisedTokenCount = 0;}static void PackModes (CP_INSTANCE *cpi) { ogg_uint32_t i,j; unsigned char ModeIndex; unsigned char *SchemeList; unsigned char BestModeSchemes[MAX_MODES]; ogg_int32_t ModeCount[MAX_MODES]; ogg_int32_t TmpFreq = -1; ogg_int32_t TmpIndex = -1; ogg_uint32_t BestScheme; ogg_uint32_t BestSchemeScore; ogg_uint32_t SchemeScore; oggpack_buffer *opb=cpi->oggbuffer; /* Build a frequency map for the modes in this frame */ memset( ModeCount, 0, MAX_MODES*sizeof(ogg_int32_t) ); for ( i = 0; i < cpi->ModeListCount; i++ ) ModeCount[cpi->ModeList[i]] ++; /* Order the modes from most to least frequent. Store result as scheme 0 */ for ( j = 0; j < MAX_MODES; j++ ) { TmpFreq = -1; /* need to re-initialize for each loop */ /* Find the most frequent */ for ( i = 0; i < MAX_MODES; i++ ) { /* Is this the best scheme so far ??? */ if ( ModeCount[i] > TmpFreq ) { TmpFreq = ModeCount[i]; TmpIndex = i; } } /* I don't know if the above loop ever fails to match, but it's better safe than sorry. Plus this takes care of gcc warning */ if ( TmpIndex != -1 ) { ModeCount[TmpIndex] = -1; BestModeSchemes[TmpIndex] = (unsigned char)j; } } /* Default/ fallback scheme uses MODE_BITS bits per mode entry */ BestScheme = (MODE_METHODS - 1); BestSchemeScore = cpi->ModeListCount * 3; /* Get a bit score for the available schemes. */ for ( j = 0; j < (MODE_METHODS - 1); j++ ) { /* Reset the scheme score */ if ( j == 0 ){ /* Scheme 0 additional cost of sending frequency order */ SchemeScore = 24; SchemeList = BestModeSchemes; } else { SchemeScore = 0; SchemeList = ModeSchemes[j-1]; } /* Find the total bits to code using each avaialable scheme */ for ( i = 0; i < cpi->ModeListCount; i++ ) SchemeScore += ModeBitLengths[SchemeList[cpi->ModeList[i]]]; /* Is this the best scheme so far ??? */ if ( SchemeScore < BestSchemeScore ) { BestSchemeScore = SchemeScore; BestScheme = j; } } /* Encode the best scheme. */ oggpackB_write( opb, BestScheme, (ogg_uint32_t)MODE_METHOD_BITS ); /* If the chosen schems is scheme 0 send details of the mode frequency order */ if ( BestScheme == 0 ) { for ( j = 0; j < MAX_MODES; j++ ) /* Note that the last two entries are implicit */ oggpackB_write( opb, BestModeSchemes[j], (ogg_uint32_t)MODE_BITS ); SchemeList = BestModeSchemes; } else { SchemeList = ModeSchemes[BestScheme-1]; } /* Are we using one of the alphabet based schemes or the fallback scheme */ if ( BestScheme < (MODE_METHODS - 1)) { /* Pack and encode the Mode list */ for ( i = 0; i < cpi->ModeListCount; i++ ) { /* Add the appropriate mode entropy token. */ ModeIndex = SchemeList[cpi->ModeList[i]]; oggpackB_write( opb, ModeBitPatterns[ModeIndex], (ogg_uint32_t)ModeBitLengths[ModeIndex] ); } }else{ /* Fall back to MODE_BITS per entry */ for ( i = 0; i < cpi->ModeListCount; i++ ) { /* Add the appropriate mode entropy token. */ oggpackB_write( opb, cpi->ModeList[i], MODE_BITS ); } }}static void PackMotionVectors (CP_INSTANCE *cpi) { ogg_int32_t i; ogg_uint32_t MethodBits[2] = {0,0};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -