📄 mbcoding.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - MB coding - * * Copyright (C) 2002 Michael Militzer <isibaar@xvid.org> * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: mbcoding.c,v 1.52.2.2 2007/06/28 15:00:11 Isibaar Exp $ * ****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "../portab.h"#include "../global.h"#include "bitstream.h"#include "zigzag.h"#include "vlc_codes.h"#include "mbcoding.h"#include "../utils/mbfunctions.h"#define LEVELOFFSET 32/* Initialized once during xvid_global call * RO access is thread safe */static REVERSE_EVENT DCT3D[2][4096];static VLC coeff_VLC[2][2][64][64];/* not really MB related, but VLCs are only available here */void bs_put_spritetrajectory(Bitstream * bs, const int val){ const int code = sprite_trajectory_code[val+16384].code; const int len = sprite_trajectory_code[val+16384].len; const int code2 = sprite_trajectory_len[len].code; const int len2 = sprite_trajectory_len[len].len;#if 0 printf("GMC=%d Code/Len = %d / %d ",val, code,len); printf("Code2 / Len2 = %d / %d \n",code2,len2);#endif BitstreamPutBits(bs, code2, len2); if (len) BitstreamPutBits(bs, code, len);}int bs_get_spritetrajectory(Bitstream * bs){ int i; for (i = 0; i < 12; i++) { if (BitstreamShowBits(bs, sprite_trajectory_len[i].len) == sprite_trajectory_len[i].code) { BitstreamSkip(bs, sprite_trajectory_len[i].len); return i; } } return -1;}voidinit_vlc_tables(void){ uint32_t i, j, k, intra, last, run, run_esc, level, level_esc, escape, escape_len, offset; int32_t l; for (intra = 0; intra < 2; intra++) for (i = 0; i < 4096; i++) DCT3D[intra][i].event.level = 0; for (intra = 0; intra < 2; intra++) { for (last = 0; last < 2; last++) { for (run = 0; run < 63 + last; run++) { for (level = 0; level < (uint32_t)(32 << intra); level++) { offset = !intra * LEVELOFFSET; coeff_VLC[intra][last][level + offset][run].len = 128; } } } } for (intra = 0; intra < 2; intra++) { for (i = 0; i < 102; i++) { offset = !intra * LEVELOFFSET; for (j = 0; j < (uint32_t)(1 << (12 - coeff_tab[intra][i].vlc.len)); j++) { DCT3D[intra][(coeff_tab[intra][i].vlc.code << (12 - coeff_tab[intra][i].vlc.len)) | j].len = coeff_tab[intra][i].vlc.len; DCT3D[intra][(coeff_tab[intra][i].vlc.code << (12 - coeff_tab[intra][i].vlc.len)) | j].event = coeff_tab[intra][i].event; } coeff_VLC[intra][coeff_tab[intra][i].event.last][coeff_tab[intra][i].event.level + offset][coeff_tab[intra][i].event.run].code = coeff_tab[intra][i].vlc.code << 1; coeff_VLC[intra][coeff_tab[intra][i].event.last][coeff_tab[intra][i].event.level + offset][coeff_tab[intra][i].event.run].len = coeff_tab[intra][i].vlc.len + 1; if (!intra) { coeff_VLC[intra][coeff_tab[intra][i].event.last][offset - coeff_tab[intra][i].event.level][coeff_tab[intra][i].event.run].code = (coeff_tab[intra][i].vlc.code << 1) | 1; coeff_VLC[intra][coeff_tab[intra][i].event.last][offset - coeff_tab[intra][i].event.level][coeff_tab[intra][i].event.run].len = coeff_tab[intra][i].vlc.len + 1; } } } for (intra = 0; intra < 2; intra++) { for (last = 0; last < 2; last++) { for (run = 0; run < 63 + last; run++) { for (level = 1; level < (uint32_t)(32 << intra); level++) { if (level <= max_level[intra][last][run] && run <= max_run[intra][last][level]) continue; offset = !intra * LEVELOFFSET; level_esc = level - max_level[intra][last][run]; run_esc = run - 1 - max_run[intra][last][level]; if (level_esc <= max_level[intra][last][run] && run <= max_run[intra][last][level_esc]) { escape = ESCAPE1; escape_len = 7 + 1; run_esc = run; } else { if (run_esc <= max_run[intra][last][level] && level <= max_level[intra][last][run_esc]) { escape = ESCAPE2; escape_len = 7 + 2; level_esc = level; } else { if (!intra) { coeff_VLC[intra][last][level + offset][run].code = (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | ((level & 0xfff) << 1) | 1; coeff_VLC[intra][last][level + offset][run].len = 30; coeff_VLC[intra][last][offset - level][run].code = (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | ((-(int32_t)level & 0xfff) << 1) | 1; coeff_VLC[intra][last][offset - level][run].len = 30; } continue; } } coeff_VLC[intra][last][level + offset][run].code = (escape << coeff_VLC[intra][last][level_esc + offset][run_esc].len) | coeff_VLC[intra][last][level_esc + offset][run_esc].code; coeff_VLC[intra][last][level + offset][run].len = coeff_VLC[intra][last][level_esc + offset][run_esc].len + escape_len; if (!intra) { coeff_VLC[intra][last][offset - level][run].code = (escape << coeff_VLC[intra][last][level_esc + offset][run_esc].len) | coeff_VLC[intra][last][level_esc + offset][run_esc].code | 1; coeff_VLC[intra][last][offset - level][run].len = coeff_VLC[intra][last][level_esc + offset][run_esc].len + escape_len; } } if (!intra) { coeff_VLC[intra][last][0][run].code = (ESCAPE3 << 21) | (last << 20) | (run << 14) | (1 << 13) | ((-32 & 0xfff) << 1) | 1; coeff_VLC[intra][last][0][run].len = 30; } } } } /* init sprite_trajectory tables * even if GMC is not specified (it might be used later...) */ sprite_trajectory_code[0+16384].code = 0; sprite_trajectory_code[0+16384].len = 0; for (k=0;k<14;k++) { int limit = (1<<k); for (l=-(2*limit-1); l <= -limit; l++) { sprite_trajectory_code[l+16384].code = (2*limit-1)+l; sprite_trajectory_code[l+16384].len = k+1; } for (l=limit; l<= 2*limit-1; l++) { sprite_trajectory_code[l+16384].code = l; sprite_trajectory_code[l+16384].len = k+1; } }}static __inline voidCodeVector(Bitstream * bs, int32_t value, int32_t f_code){ const int scale_factor = 1 << (f_code - 1); const int cmp = scale_factor << 5; if (value < (-1 * cmp)) value += 64 * scale_factor; if (value > (cmp - 1)) value -= 64 * scale_factor; if (value == 0) { BitstreamPutBits(bs, mb_motion_table[32].code, mb_motion_table[32].len); } else { uint16_t length, code, mv_res, sign; length = 16 << f_code; f_code--; sign = (value < 0); if (value >= length) value -= 2 * length; else if (value < -length) value += 2 * length; if (sign) value = -value; value--; mv_res = value & ((1 << f_code) - 1); code = ((value - mv_res) >> f_code) + 1; if (sign) code = -code; code += 32; BitstreamPutBits(bs, mb_motion_table[code].code, mb_motion_table[code].len); if (f_code) BitstreamPutBits(bs, mv_res, f_code); }}static __inline voidCodeCoeffInter(Bitstream * bs, const int16_t qcoeff[64], const uint16_t * zigzag){ uint32_t i, run, prev_run, code, len; int32_t level, prev_level, level_shifted; i = 0; run = 0; while (!(level = qcoeff[zigzag[i++]])) run++; prev_level = level; prev_run = run; run = 0; while (i < 64) { if ((level = qcoeff[zigzag[i++]]) != 0) { level_shifted = prev_level + 32; if (!(level_shifted & -64)) { code = coeff_VLC[0][0][level_shifted][prev_run].code; len = coeff_VLC[0][0][level_shifted][prev_run].len; } else { code = (ESCAPE3 << 21) | (prev_run << 14) | (1 << 13) | ((prev_level & 0xfff) << 1) | 1; len = 30; } BitstreamPutBits(bs, code, len); prev_level = level; prev_run = run; run = 0; } else run++; } level_shifted = prev_level + 32; if (!(level_shifted & -64)) { code = coeff_VLC[0][1][level_shifted][prev_run].code; len = coeff_VLC[0][1][level_shifted][prev_run].len; } else { code = (ESCAPE3 << 21) | (1 << 20) | (prev_run << 14) | (1 << 13) | ((prev_level & 0xfff) << 1) | 1; len = 30; } BitstreamPutBits(bs, code, len);}static __inline voidCodeCoeffIntra(Bitstream * bs, const int16_t qcoeff[64], const uint16_t * zigzag){ uint32_t i, abs_level, run, prev_run, code, len; int32_t level, prev_level; i = 1; run = 0; while (i<64 && !(level = qcoeff[zigzag[i++]])) run++; prev_level = level; prev_run = run; run = 0; while (i < 64) { if ((level = qcoeff[zigzag[i++]]) != 0) { abs_level = abs(prev_level); abs_level = abs_level < 64 ? abs_level : 0; code = coeff_VLC[1][0][abs_level][prev_run].code; len = coeff_VLC[1][0][abs_level][prev_run].len; if (len != 128) code |= (prev_level < 0); else { code = (ESCAPE3 << 21) | (prev_run << 14) | (1 << 13) | ((prev_level & 0xfff) << 1) | 1; len = 30; } BitstreamPutBits(bs, code, len); prev_level = level; prev_run = run; run = 0; } else run++; } abs_level = abs(prev_level); abs_level = abs_level < 64 ? abs_level : 0; code = coeff_VLC[1][1][abs_level][prev_run].code; len = coeff_VLC[1][1][abs_level][prev_run].len; if (len != 128) code |= (prev_level < 0); else { code = (ESCAPE3 << 21) | (1 << 20) | (prev_run << 14) | (1 << 13) | ((prev_level & 0xfff) << 1) | 1; len = 30; } BitstreamPutBits(bs, code, len);}/* returns the number of bits required to encode qcoeff */intCodeCoeffIntra_CalcBits(const int16_t qcoeff[64], const uint16_t * zigzag){ int bits = 0; uint32_t i, abs_level, run, prev_run, len; int32_t level, prev_level; i = 1; run = 0; while (i<64 && !(level = qcoeff[zigzag[i++]])) run++; if (i >= 64) return 0; /* empty block */ prev_level = level; prev_run = run; run = 0; while (i < 64) { if ((level = qcoeff[zigzag[i++]]) != 0) { abs_level = abs(prev_level); abs_level = abs_level < 64 ? abs_level : 0; len = coeff_VLC[1][0][abs_level][prev_run].len; bits += len!=128 ? len : 30; prev_level = level; prev_run = run; run = 0; } else run++; } abs_level = abs(prev_level); abs_level = abs_level < 64 ? abs_level : 0; len = coeff_VLC[1][1][abs_level][prev_run].len; bits += len!=128 ? len : 30; return bits;}intCodeCoeffInter_CalcBits(const int16_t qcoeff[64], const uint16_t * zigzag){ uint32_t i, run, prev_run, len; int32_t level, prev_level, level_shifted; int bits = 0; i = 0; run = 0; while (!(level = qcoeff[zigzag[i++]])) run++; prev_level = level; prev_run = run; run = 0; while (i < 64) { if ((level = qcoeff[zigzag[i++]]) != 0) { level_shifted = prev_level + 32; if (!(level_shifted & -64)) len = coeff_VLC[0][0][level_shifted][prev_run].len; else len = 30; bits += len; prev_level = level; prev_run = run; run = 0; } else run++; } level_shifted = prev_level + 32; if (!(level_shifted & -64)) len = coeff_VLC[0][1][level_shifted][prev_run].len; else len = 30; bits += len; return bits;}static const int iDQtab[5] = { 1, 0, -1 /* no change */, 2, 3};#define DQ_VALUE2INDEX(value) iDQtab[(value)+2]static __inline voidCodeBlockIntra(const FRAMEINFO * const frame, const MACROBLOCK * pMB, int16_t qcoeff[6 * 64], Bitstream * bs, Statistics * pStat){ uint32_t i, mcbpc, cbpy, bits; cbpy = pMB->cbp >> 2; /* write mcbpc */ if (frame->coding_type == I_VOP) { mcbpc = ((pMB->mode >> 1) & 3) | ((pMB->cbp & 3) << 2); BitstreamPutBits(bs, mcbpc_intra_tab[mcbpc].code, mcbpc_intra_tab[mcbpc].len); } else { mcbpc = (pMB->mode & 7) | ((pMB->cbp & 3) << 3); BitstreamPutBits(bs, mcbpc_inter_tab[mcbpc].code, mcbpc_inter_tab[mcbpc].len); } /* ac prediction flag */ if (pMB->acpred_directions[0]) BitstreamPutBits(bs, 1, 1); else BitstreamPutBits(bs, 0, 1); /* write cbpy */ BitstreamPutBits(bs, xvid_cbpy_tab[cbpy].code, xvid_cbpy_tab[cbpy].len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -