📄 vlc.cpp
字号:
/** * Copyright (c) 2006 * OpenAVS Developers. All Rights Reserved. * * Copyright (c) 2005-2006 * NSCC. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *//** * ! \file "vlc.c" * \brief Functions related to VLC decoding process. */#include "vlc.h"#include "define.h"#include "global.h"#include "assert.h"#include "memory.h"static AVS_I8 AVS_2DVLC_INTRA_dec[7][64][2] = { { {-1, -1} } };static AVS_I8 AVS_2DVLC_INTER_dec[7][64][2] = { { {-1, -1} } };static AVS_I8 AVS_2DVLC_CHROMA_dec[5][64][2] = { { {-1, -1} } };static const AVS_INT EOB_Pos_intra[7] = {-1, 8, 8, 8, 6, 0, 0};static const AVS_INT EOB_Pos_inter[7] = {-1, 2, 2, 2, 2, 0, 0};static void linfo_ue(AVS_INT len, AVS_INT info, AVS_INT *value1);static void linfo_se(AVS_INT len, AVS_INT info, AVS_INT *value1);static void linfo_cbp_intra(AVS_INT len,AVS_INT info,AVS_INT *cbp);static void linfo_cbp_inter(AVS_INT len,AVS_INT info,AVS_INT *cbp);/** * Function: Count the leading zero bits in data stream. * Used in decoding Exponential-Golomb(Exp-Golomb). */static AVS_INT PassLeadingZeroBits(const AVS_BYTE * buffer, AVS_DWORD * totbitoffset){ AVS_LONG byteoffset; /* byte from start of buffer */ AVS_INT bitLeft; /* bit from start of byte */ AVS_INT findtag; AVS_INT oldbitoffset = *totbitoffset; findtag = 0; byteoffset = (*totbitoffset) / 8; bitLeft= 31 - ((*totbitoffset) & 7); AVS_INT data = DWORD_SWAP(*(AVS_DWORD*)(buffer + byteoffset)); while (! findtag) { findtag = (data & (0x01 << bitLeft)); bitLeft--; (*totbitoffset)++; } return *totbitoffset - oldbitoffset - 1;}/** * Function: Read numbits from current position. * Used in decoding fixed-/variable-length coding. */AVS_INT read_bits(const AVS_BYTE * buffer, AVS_DWORD * totbitoffset, AVS_INT numbits){ if (numbits == 0) return 0; AVS_INT inf; AVS_INT byteoffset = (*totbitoffset) >> 3; AVS_INT bitoffset = (*totbitoffset) & 7; AVS_INT bitleft = 31 - bitoffset; AVS_UINT data = DWORD_SWAP(*(AVS_DWORD*)(buffer + byteoffset)); *totbitoffset += numbits; AVS_UINT tmp = data << bitoffset; inf = tmp >> (32 - numbits); return inf;}AVS_INT se(const AVS_BYTE * buffer,AVS_DWORD * totbitoffset, AVS_INT bytecount){ AVS_INT info = 0; AVS_INT value1= 0; AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset); info = read_bits(buffer, totbitoffset, len); linfo_se(len, info, &value1); return value1;}AVS_INT ue(const AVS_BYTE * buffer,AVS_DWORD * totbitoffset, AVS_INT bytecount){ AVS_INT info = 0; AVS_INT value1; AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset); info = read_bits(buffer, totbitoffset, len); linfo_ue(len * 2 + 1, info, &value1); return value1; }static void linfo_ue(AVS_INT len, AVS_INT info, AVS_INT *value1){ AVS_INT n = 1 << (len / 2); info --; *value1 = n + info;}static void linfo_se(AVS_INT len, AVS_INT info, AVS_INT * value1){ AVS_INT n; n = 1<< len; n += info; if (n & 1) *value1 = -(n >> 1); else *value1 = (n >> 1);}static void linfo_cbp_intra(AVS_INT len, AVS_INT info, AVS_INT * cbp){ AVS_INT cbp_idx; linfo_ue(len, info, &cbp_idx); *cbp = NCBP[cbp_idx][0];}static void linfo_cbp_inter(AVS_INT len, AVS_INT info, AVS_INT * cbp){ AVS_INT cbp_idx; linfo_ue(len, info, &cbp_idx); *cbp = NCBP[cbp_idx][1];}static void linfo_cbp_intra422(AVS_INT len, AVS_INT info, AVS_INT * cbp){ AVS_INT cbp_idx; linfo_ue(len, info, &cbp_idx); *cbp = NCBP422[cbp_idx][0];}static void linfo_cbp_inter422(AVS_INT len, AVS_INT info, AVS_INT *cbp){ AVS_INT cbp_idx; linfo_ue(len, info, &cbp_idx); *cbp = NCBP422[cbp_idx][1];}AVS_INT me(const AVS_BYTE* buffer,AVS_DWORD* totbitoffset, AVS_INT bytecount, AVS_DWORD dwMbType){ AVS_INT cbp = 0; AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset); AVS_INT info = read_bits(buffer, totbitoffset, len); if (dwMbType == I_8x8) { /* Infra */ linfo_cbp_intra(len * 2 + 1, info, &cbp); } else { /* Inter */ linfo_cbp_inter(len * 2 + 1, info, &cbp); } return cbp;}AVS_INT me_chroma422( const AVS_BYTE * buffer, AVS_DWORD * totbitoffset, AVS_INT bytecount, AVS_DWORD dwMbType){ AVS_INT cbp = 0; AVS_INT len = PassLeadingZeroBits(buffer, totbitoffset); AVS_INT info = read_bits(buffer, totbitoffset, len); if (dwMbType == I_8x8) linfo_cbp_intra422(len * 2 + 1, info, &cbp); else linfo_cbp_inter422(len * 2 + 1, info, &cbp); return cbp;}/** * Function: Initialize VLC table. */void MakeVlcTable(){ AVS_INT level, run, ipos; AVS_INT i; /* make decoder table for 2DVLC_INTRA code */ /* Don't need to set this every time. rewrite later. */ if (AVS_2DVLC_INTRA_dec[0][0][1] < 0) { memset(AVS_2DVLC_INTRA_dec, -1, sizeof(AVS_2DVLC_INTRA_dec)); for (i=0; i < 7; i++) { for (run = 0; run < 26; run++) for (level = 0; level < 27; level++) { ipos = AVS_2DVLC_INTRA[i][run][level]; assert(ipos < 64); if (ipos >= 0) { if(i == 0) { AVS_2DVLC_INTRA_dec[i][ipos][0] = level + 1; AVS_2DVLC_INTRA_dec[i][ipos][1] = run; AVS_2DVLC_INTRA_dec[i][ipos + 1][0] = -(level + 1); AVS_2DVLC_INTRA_dec[i][ipos + 1][1] = run; } else { AVS_2DVLC_INTRA_dec[i][ipos][0]=level; AVS_2DVLC_INTRA_dec[i][ipos][1]=run; if (level == 0) continue; AVS_2DVLC_INTRA_dec[i][ipos + 1][0] = -(level); AVS_2DVLC_INTRA_dec[i][ipos + 1][1] = run; } } } } /* otherwise, tables are bad. */ assert(AVS_2DVLC_INTRA_dec[0][0][1] >= 0); } /* make decoder table for 2DVLC_INTER code */ /* Don't need to set this every time. rewrite later. */ if (AVS_2DVLC_INTER_dec[0][0][1] < 0) { memset(AVS_2DVLC_INTER_dec, -1, sizeof(AVS_2DVLC_INTER_dec)); for (i = 0; i < 7; i++) { for (run = 0; run < 26; run++) for (level = 0; level < 27;level++) { ipos = AVS_2DVLC_INTER[i][run][level]; assert(ipos < 64); if (ipos < 0) continue; if (i == 0) { AVS_2DVLC_INTER_dec[i][ipos][0] = level + 1; AVS_2DVLC_INTER_dec[i][ipos][1] = run; AVS_2DVLC_INTER_dec[i][ipos+1][0] = -(level + 1); AVS_2DVLC_INTER_dec[i][ipos+1][1] = run; } else { AVS_2DVLC_INTER_dec[i][ipos][0] = level; AVS_2DVLC_INTER_dec[i][ipos][1] = run; if (level == 0) continue; AVS_2DVLC_INTER_dec[i][ipos+1][0] = -(level); AVS_2DVLC_INTER_dec[i][ipos+1][1] = run; } } } /* otherwise, tables are bad. */ assert(AVS_2DVLC_INTER_dec[0][0][1] >= 0); } /* make decoder table for 2DVLC_CHROMA code */ /* Don't need to set this every time. rewrite later. */ if (AVS_2DVLC_CHROMA_dec[0][0][1] < 0) { memset(AVS_2DVLC_CHROMA_dec, -1, sizeof(AVS_2DVLC_CHROMA_dec)); for (i = 0; i < 5; i++) { for (run = 0; run < 26; run++) for (level = 0; level < 27; level++) { ipos = AVS_2DVLC_CHROMA[i][run][level]; assert(ipos < 64); if (ipos < 0) continue; if (i == 0) { AVS_2DVLC_CHROMA_dec[i][ipos][0] = level + 1; AVS_2DVLC_CHROMA_dec[i][ipos][1] = run; AVS_2DVLC_CHROMA_dec[i][ipos + 1][0] = -(level + 1); AVS_2DVLC_CHROMA_dec[i][ipos + 1][1] = run; } else { AVS_2DVLC_CHROMA_dec[i][ipos][0] = level; AVS_2DVLC_CHROMA_dec[i][ipos][1] = run; if (level == 0) continue; AVS_2DVLC_CHROMA_dec[i][ipos + 1][0] = -(level); AVS_2DVLC_CHROMA_dec[i][ipos + 1][1] = run; } } } /* otherwise, tables are bad. */ assert(AVS_2DVLC_CHROMA_dec[0][0][1] >= 0); }}void ReadLumaCoeff( const AVS_BYTE * pbCurrent, AVS_DWORD dwDataLen, AVS_DWORD * pdwBitOffset, MBINFO * pCurrMb, AVS_DWORD dwPictureStructure, AVS_SHORT* pResidual){ static const AVS_INT incVlc_intra[7] = { 0, 1, 2, 4, 7, 10, 3000 }; static const AVS_INT incVlc_inter[7] = { 0, 1, 2, 3, 6, 9, 3000 }; AVS_INT i; AVS_INT ii, jj; AVS_DWORD tabNo = 0; AVS_INT symbol2D; AVS_INT vlc_numcoef = 0; AVS_INT run = 0, level = 0; AVS_INT buffer_level[65]; AVS_INT buffer_run[65]; AVS_INT* TABNO = TabNoBuf + 512; AVS_INT* TABNO2 = TabNoBuf2 + 512; AVS_INT qp, shift; qp = pCurrMb->dwMbQp; AVS_INT QPI, sum; AVS_INT ipos = -1; AVS_INT Golomb_se_type = SE_LUM_AC_INTER; AVS_INT leadingZeroBits; AVS_INT grad; AVS_INT val, val2; memset(buffer_run, 0, 65 * sizeof(AVS_INT)); memset(buffer_level, 0, 65 * sizeof(AVS_INT)); if (pCurrMb->dwMbType == I_8x8) { for (i = 0; i < 65; i++) { leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset); grad = VLC_Golomb_Order[0][tabNo][0]; val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits + grad); symbol2D = (1 << (leadingZeroBits + grad)) - (1 << grad) + val; if (symbol2D == EOB_Pos_intra[tabNo]) { vlc_numcoef = i; break; } else if (symbol2D < CODE2D_ESCAPE_SYMBOL) { level = AVS_2DVLC_INTRA_dec[tabNo][symbol2D][0]; run = AVS_2DVLC_INTRA_dec[tabNo][symbol2D][1]; } else { run = (symbol2D - CODE2D_ESCAPE_SYMBOL) >> 1; leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset); grad = 1; val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad); val2 = (1 << (leadingZeroBits+grad)) - (1 << grad) + val; level = val2 + ((run>MaxRun[0][tabNo])?1:RefAbsLevel[tabNo][run]); if (symbol2D & 1) level = -level; } buffer_level[i] = level; buffer_run[i] = run; if (abs(level) > incVlc_intra[tabNo]) { tabNo = TABNO[level]; } } for (i = (vlc_numcoef - 1); i>=0; i--) { ipos += (buffer_run[i] + 1); ii = SCAN[dwPictureStructure][ipos][0]; jj = SCAN[dwPictureStructure][ipos][1]; shift = IQ_SHIFT[qp]; QPI = IQ_TAB[qp]; val = buffer_level[i]; sum = (val * QPI + (1 << (shift - 2))) >> (shift - 1); *(pResidual + jj * 8 + ii) = sum; } } else { tabNo = 0; for (i = 0; i < 65; i++) { leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset); grad = VLC_Golomb_Order[1][tabNo][0]; val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits + grad); symbol2D = (1 << (leadingZeroBits + grad)) - (1 << grad) + val; if (symbol2D == EOB_Pos_inter[tabNo]) { vlc_numcoef = i; break; } else if (symbol2D < CODE2D_ESCAPE_SYMBOL) { level = AVS_2DVLC_INTER_dec[tabNo][symbol2D][0]; run = AVS_2DVLC_INTER_dec[tabNo][symbol2D][1]; } else { run = (symbol2D - CODE2D_ESCAPE_SYMBOL) >> 1; leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset); grad = 0; val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits + grad); val2 = (1 << (leadingZeroBits+grad)) - (1 << grad) + val; level = val2 + ((run > MaxRun[1][tabNo]) ? 1 : RefAbsLevel[tabNo+7][run]); if (symbol2D & 1) level=-level; } buffer_level[i] = level; buffer_run[i] = run; if (abs(level) > incVlc_inter[tabNo]) { tabNo = TABNO2[level]; } } /* store encoded level,run to LumaCoeff[][] */ for (i = (vlc_numcoef - 1); i >= 0; i--) { ipos += (buffer_run[i] + 1); ii = SCAN[dwPictureStructure][ipos][0]; jj = SCAN[dwPictureStructure][ipos][1]; shift = IQ_SHIFT[qp]; QPI = IQ_TAB[qp]; val = buffer_level[i]; sum = (val * QPI + (1 << (shift - 2))) >> (shift - 1); *(pResidual + jj * 8 + ii) = sum; } }}void ReadChromaCoeff( const AVS_BYTE * pbCurrent, AVS_DWORD dwDataLen, AVS_DWORD * pdwBitOffset, MBINFO * pCurrMb, AVS_DWORD dwPictureStructure, AVS_SHORT * pResidual){ AVS_INT tabNo = 0; AVS_INT symbol2D = 0; AVS_INT vlc_numcoef = 0; AVS_INT run, level; AVS_INT buffer_level[65]; AVS_INT buffer_run[65]; static const AVS_INT EOB_Pos_chroma[2][5] = { {-1, 4, 8, 6, 4}, {-1, 0, 2, 0, 0} }; static const AVS_INT incVlc_chroma[5] = {0, 1, 2, 4, 3000}; AVS_INT leadingZeroBits; AVS_INT grad; AVS_INT val, val2; /* using old style qp */ AVS_INT qp_chroma = QP_SCALE_CR[pCurrMb->dwMbQp]; AVS_INT temp; AVS_INT ii, jj; AVS_INT shift, QPI; AVS_INT ipos = -1; for (AVS_INT i = 0; i < 65; i++) { leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset); grad = VLC_Golomb_Order[2][tabNo][0]; val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad); symbol2D = (1 << (leadingZeroBits + grad)) - (1 << grad) + val; if (symbol2D == EOB_Pos_chroma[1][tabNo]) { vlc_numcoef = i; break; } if (symbol2D < CODE2D_ESCAPE_SYMBOL) { level = AVS_2DVLC_CHROMA_dec[tabNo][symbol2D][0]; run = AVS_2DVLC_CHROMA_dec[tabNo][symbol2D][1]; } else { run = (symbol2D-CODE2D_ESCAPE_SYMBOL) >> 1; leadingZeroBits = PassLeadingZeroBits(pbCurrent, pdwBitOffset); grad = 0; val = read_bits(pbCurrent, pdwBitOffset, leadingZeroBits+grad); val2 = (1 << (leadingZeroBits + grad)) - (1 << grad) + val; level = val2 + ((run>MaxRun[2][tabNo])?1:RefAbsLevel[tabNo+14][run]); if (symbol2D & 1) level = -level; } buffer_level[i] = level; buffer_run[i] = run; if (abs(level) > incVlc_chroma[tabNo]) { if (abs(level) <= 2) tabNo = abs(level); else if (abs(level) <= 4) tabNo = 3; else tabNo = 4; } } for (AVS_INT i = (vlc_numcoef - 1); i >= 0; i--) { ipos += (buffer_run[i] + 1); ii = SCAN[dwPictureStructure][ipos][0]; jj = SCAN[dwPictureStructure][ipos][1]; shift = IQ_SHIFT[qp_chroma]; QPI = IQ_TAB[qp_chroma]; val = buffer_level[i]; temp = (val * QPI + (1 << (shift - 2))) >> (shift - 1); *(pResidual + jj * 8 + ii) = temp; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -