📄 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 2005/09/13 12:12:15 suxen_drol 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"#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];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; } }}/* returns the number of bits required to encode qcoeff */static const int iDQtab[5] = { 1, 0, -1 /* no change */, 2, 3};#define DQ_VALUE2INDEX(value) iDQtab[(value)+2]/*************************************************************** * decoding stuff starts here * ***************************************************************//* * for IVOP addbits == 0 * for PVOP addbits == fcode - 1 * for BVOP addbits == max(fcode,bcode) - 1 * returns true or false */intcheck_resync_marker(Bitstream * bs, int addbits){ uint32_t nbits; uint32_t code; uint32_t nbitsresyncmarker = NUMBITS_VP_RESYNC_MARKER + addbits; nbits = BitstreamNumBitsToByteAlign(bs); code = BitstreamShowBits(bs, nbits); if (code == (((uint32_t)1 << (nbits - 1)) - 1)) { return BitstreamShowBitsFromByteAlign(bs, nbitsresyncmarker) == RESYNC_MARKER; } return 0;}intget_mcbpc_intra(Bitstream * bs){ uint32_t index; index = BitstreamShowBits(bs, 9); index >>= 3; BitstreamSkip(bs, mcbpc_intra_table[index].len); return mcbpc_intra_table[index].code;}intget_mcbpc_inter(Bitstream * bs){ uint32_t index; index = MIN(BitstreamShowBits(bs, 9), 256); BitstreamSkip(bs, mcbpc_inter_table[index].len); return mcbpc_inter_table[index].code;}intget_cbpy(Bitstream * bs, int intra){ int cbpy; uint32_t index = BitstreamShowBits(bs, 6); BitstreamSkip(bs, cbpy_table[index].len); cbpy = cbpy_table[index].code; if (!intra) cbpy = 15 - cbpy; return cbpy;}static __inline intget_mv_data(Bitstream * bs){ uint32_t index; if (BitstreamGetBit(bs)) return 0; index = BitstreamShowBits(bs, 12); if (index >= 512) { index = (index >> 8) - 2; BitstreamSkip(bs, TMNMVtab0[index].len); return TMNMVtab0[index].code; } if (index >= 128) { index = (index >> 2) - 32; BitstreamSkip(bs, TMNMVtab1[index].len); return TMNMVtab1[index].code; } index -= 4; BitstreamSkip(bs, TMNMVtab2[index].len); return TMNMVtab2[index].code;}intget_mv(Bitstream * bs, int fcode){ int data; int res; int mv; int scale_fac = 1 << (fcode - 1); data = get_mv_data(bs); if (scale_fac == 1 || data == 0) return data; res = BitstreamGetBits(bs, fcode - 1); mv = ((abs(data) - 1) * scale_fac) + res + 1; return data < 0 ? -mv : mv;}intget_dc_dif(Bitstream * bs, uint32_t dc_size){ int code = BitstreamGetBits(bs, dc_size); int msb = code >> (dc_size - 1); if (msb == 0) return (-1 * (code ^ ((1 << dc_size) - 1))); return code;}intget_dc_size_lum(Bitstream * bs){ int code, i; code = BitstreamShowBits(bs, 11); for (i = 11; i > 3; i--) { if (code == 1) { BitstreamSkip(bs, i); return i + 1; } code >>= 1; } BitstreamSkip(bs, dc_lum_tab[code].len); return dc_lum_tab[code].code;}intget_dc_size_chrom(Bitstream * bs){ uint32_t code, i; code = BitstreamShowBits(bs, 12); for (i = 12; i > 2; i--) { if (code == 1) { BitstreamSkip(bs, i); return i; } code >>= 1; } return 3 - BitstreamGetBits(bs, 2);}#define GET_BITS(cache, n) ((cache)>>(32-(n)))static __inline intget_coeff(Bitstream * bs, int *run, int *last, int intra, int short_video_header){ uint32_t mode; int32_t level; REVERSE_EVENT *reverse_event; uint32_t cache = BitstreamShowBits(bs, 32); if (short_video_header) /* inter-VLCs will be used for both intra and inter blocks */ intra = 0; if (GET_BITS(cache, 7) != ESCAPE) { reverse_event = &DCT3D[intra][GET_BITS(cache, 12)]; if ((level = reverse_event->event.level) == 0) goto error; *last = reverse_event->event.last; *run = reverse_event->event.run; /* Don't forget to update the bitstream position */ BitstreamSkip(bs, reverse_event->len+1); return (GET_BITS(cache, reverse_event->len+1)&0x01) ? -level : level; } /* flush 7bits of cache */ cache <<= 7; if (short_video_header) { /* escape mode 4 - H.263 type, only used if short_video_header = 1 */ *last = GET_BITS(cache, 1); *run = (GET_BITS(cache, 7) &0x3f); level = (GET_BITS(cache, 15)&0xff); if (level == 0 || level == 128) DPRINTF(XVID_DEBUG_ERROR, "Illegal LEVEL for ESCAPE mode 4: %d\n", level); /* We've "eaten" 22 bits */ BitstreamSkip(bs, 22); return (level << 24) >> 24; } if ((mode = GET_BITS(cache, 2)) < 3) { const int skip[3] = {1, 1, 2}; cache <<= skip[mode]; reverse_event = &DCT3D[intra][GET_BITS(cache, 12)]; if ((level = reverse_event->event.level) == 0) goto error; *last = reverse_event->event.last; *run = reverse_event->event.run; if (mode < 2) { /* first escape mode, level is offset */ level += max_level[intra][*last][*run]; } else { /* second escape mode, run is offset */ *run += max_run[intra][*last][level] + 1; } /* Update bitstream position */ BitstreamSkip(bs, 7 + skip[mode] + reverse_event->len + 1); return (GET_BITS(cache, reverse_event->len+1)&0x01) ? -level : level; } /* third escape mode - fixed length codes */ cache <<= 2; *last = GET_BITS(cache, 1); *run = (GET_BITS(cache, 7)&0x3f); level = (GET_BITS(cache, 20)&0xfff); /* Update bitstream position */ BitstreamSkip(bs, 30); return (level << 20) >> 20; error: *run = VLC_ERROR; return 0;}voidget_intra_block(Bitstream * bs, int16_t * block, int direction, int coeff){ const uint16_t *scan = scan_tables[direction]; int level, run, last; do { level = get_coeff(bs, &run, &last, 1, 0); if (run == -1) { DPRINTF(XVID_DEBUG_ERROR,"fatal: invalid run"); break; } coeff += run; #ifdef _DEBUG if(coeff>=64) { DPRINTF(XVID_DEBUG_ERROR,"error: overflow in coefficient index\n"); return; }#endif block[scan[coeff]] = level; DPRINTF(XVID_DEBUG_COEFF,"block[%i] %i\n", scan[coeff], level);#if 0 DPRINTF(XVID_DEBUG_COEFF,"block[%i] %i %08x\n", scan[coeff], level, BitstreamShowBits(bs, 32));#endif if (level < -2047 || level > 2047) { DPRINTF(XVID_DEBUG_ERROR,"warning: intra_overflow %i\n", level); } coeff++; } while (!last);}voidget_inter_block_h263( Bitstream * bs, int16_t * block, int direction, const int quant, const uint16_t *matrix){ const uint16_t *scan = scan_tables[direction]; const uint16_t quant_m_2 = quant << 1; const uint16_t quant_add = (quant & 1 ? quant : quant - 1); int p; int level; int run; int last; p = 0; do { level = get_coeff(bs, &run, &last, 0, 0); if (run == -1) { DPRINTF(XVID_DEBUG_ERROR,"fatal: invalid run"); break; } p += run;#ifdef _DEBUG if(p>=64) { DPRINTF(XVID_DEBUG_ERROR,"error: overflow in coefficient index\n"); return; }#endif if (level < 0) { level = level*quant_m_2 - quant_add; block[scan[p]] = (level >= -2048 ? level : -2048);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -