⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbcoding.c

📁 xvid解码的精简版本.非常好的版本,节省了分离xvid源代码的过程
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * *  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 + -