📄 mbcoding.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - Macro Block coding functions - * * Copyright(C) 2002 Michael Militzer <isibaar@xvid.org> * * This file is part of XviD, a free MPEG-4 video encoder/decoder * * XviD 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 * * Under section 8 of the GNU General Public License, the copyright * holders of XVID explicitly forbid distribution in the following * countries: * * - Japan * - United States of America * * Linking XviD statically or dynamically with other modules is making a * combined work based on XviD. Thus, the terms and conditions of the * GNU General Public License cover the whole combination. * * As a special exception, the copyright holders of XviD give you * permission to link XviD with independent modules that communicate with * XviD solely through the VFW1.1 and DShow interfaces, regardless of the * license terms of these independent modules, and to copy and distribute * the resulting combined work under terms of your choice, provided that * every copy of the combined work is accompanied by a complete copy of * the source code of XviD (the version of XviD used to produce the * combined work), being distributed under the terms of the GNU General * Public License plus this exception. An independent module is a module * which is not derived from or based on XviD. * * Note that people who make modified versions of XviD are not obligated * to grant this special exception for their modified versions; it is * their choice whether to do so. The GNU General Public License gives * permission to release a modified version without this exception; this * exception also makes it possible to release a modified version which * carries forward this exception. * * $Id: mbcoding.c,v 1.41 2003/02/13 17:31:33 edgomez Exp $ * ****************************************************************************/#include <stdlib.h>#include "../portab.h"#include "bitstream.h"#include "zigzag.h"#include "vlc_codes.h"#include "mbcoding.h"#include "../utils/mbfunctions.h"#define ABS(X) (((X)>0)?(X):-(X))#define CLIP(X,A) (X > A) ? (A) : (X)/* #define BIGLUT */#ifdef BIGLUT#define LEVELOFFSET 2048#else#define LEVELOFFSET 32#endif/***************************************************************************** * Local data ****************************************************************************/static REVERSE_EVENT DCT3D[2][4096];#ifdef BIGLUTstatic VLC coeff_VLC[2][2][4096][64];static VLC *intra_table, *inter_table; #elsestatic VLC coeff_VLC[2][2][64][64];#endif/***************************************************************************** * Vector Length Coding Initialization ****************************************************************************/voidinit_vlc_tables(void){ uint32_t i, j, intra, last, run, run_esc, level, level_esc, escape, escape_len, offset;#ifdef BIGLUT intra_table = (VLC*)coeff_VLC[1]; inter_table = (VLC*)coeff_VLC[0]; #endif 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++) {#ifdef BIGLUT offset = LEVELOFFSET;#else offset = !intra * LEVELOFFSET;#endif coeff_VLC[intra][last][level + offset][run].len = 128; } } for (intra = 0; intra < 2; intra++) for (i = 0; i < 102; i++) {#ifdef BIGLUT offset = LEVELOFFSET;#else offset = !intra * LEVELOFFSET;#endif 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;#ifndef BIGLUT if (!intra)#endif { 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;#ifdef BIGLUT offset = LEVELOFFSET;#else offset = !intra * LEVELOFFSET;#endif 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 {#ifndef BIGLUT if (!intra)#endif { 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) | ((-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;#ifndef BIGLUT if (!intra)#endif { 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; } }#ifdef BIGLUT for (level = (uint32_t)(32 << intra); level < 2048; level++) { 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) | ((-level & 0xfff) << 1) | 1; coeff_VLC[intra][last][offset - level][run].len = 30; }#else 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; }#endif } /* Shut up the compiler -- gcc 3.3 pre release */ i = dc_threshold[0];}/***************************************************************************** * Local inlined functions for MB coding ****************************************************************************/static __inline voidCodeVector(Bitstream * bs, int32_t value, int32_t f_code, Statistics * pStat){ 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; pStat->iMvSum += value * value; pStat->iMvCount++; 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); }}#ifdef BIGLUTstatic __inline voidCodeCoeff(Bitstream * bs, const int16_t qcoeff[64], VLC * table, const uint16_t * zigzag, uint16_t intra){ uint32_t j, last; short v; VLC *vlc; j = intra; last = intra; while (j < 64 && (v = qcoeff[zigzag[j]]) == 0) j++; do { vlc = table + 64 * 2048 + (v << 6) + j - last; last = ++j; /* count zeroes */ while (j < 64 && (v = qcoeff[zigzag[j]]) == 0) j++; /* write code */ if (j != 64) { BitstreamPutBits(bs, vlc->code, vlc->len); } else { vlc += 64 * 4096; BitstreamPutBits(bs, vlc->code, vlc->len); break; } } while (1);}#elsestatic __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 (!(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);}#endif/***************************************************************************** * Local functions ****************************************************************************/static voidCodeBlockIntra(const FRAMEINFO * 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -