📄 bitstream.cpp
字号:
/*****************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* - Bitstream reader/writer -
*
* Copyright (C) 2001-2003 Peter Ross <pross@xvid.org>
* 2003 Cristoph Lampert <gruel@web.de>
*
* 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: bitstream.cpp,v 1.1.1.1 2005/07/13 14:36:12 jeanlf Exp $
*
****************************************************************************/
#include "bitstream.h"
#include "quant_matrix.h"
#ifdef WIN32
#include <stdio.h>
#endif
//----------------------------
inline dword ByteSwap(dword a){
return (a<<24) | ((a&0xff00) << 8) | ((a&0xff0000) >> 8) | (a>>24);
}
//----------------------------
void Bitstream::Init(const void *bitstream, dword _length){
dword adjbitstream = (dword)bitstream;
/*
* Start the stream on a dword boundary, by rounding down to the
* previous dword and skipping the intervening bytes.
*/
long bitpos = ((sizeof(dword)-1) & (long)bitstream);
adjbitstream = adjbitstream - bitpos;
start = tail = (dword *) adjbitstream;
if(_length){
dword tmp = *start;
#ifndef ARCH_IS_BIG_ENDIAN
tmp = ByteSwap(tmp);
#endif
bufa = tmp;
if(_length>4){
tmp = *(start + 1);
#ifndef ARCH_IS_BIG_ENDIAN
tmp = ByteSwap(tmp);
#endif
bufb = tmp;
}else
bufb = 0;
}else
bufa = bufb = 0;
buf = 0;
pos = initpos = bitpos*8;
length = _length;
}
//---------------------------
/* reads n bits from bitstream without changing the stream pos */
dword Bitstream::ShowBits(dword bits){
int nbit = (bits + pos) - 32;
if(nbit > 0)
return ((bufa & (0xffffffff >> pos)) << nbit) | (bufb >> (32 - nbit));
return (bufa & (0xffffffff >> pos)) >> (32 - pos - bits);
}
//---------------------------
// skip n bits forward in bitstream
void Bitstream::Skip(dword bits){
pos += bits;
if(pos >= 32){
dword tmp;
bufa = bufb;
tmp = *((dword *) tail + 2);
#ifndef ARCH_IS_BIG_ENDIAN
tmp = ByteSwap(tmp);
#endif
bufb = tmp;
tail++;
pos -= 32;
}
}
//---------------------------
/* show nbits from next byte alignment */
dword Bitstream::ShowBitsFromByteAlign(int bits){
int bspos = pos + NumBitsToByteAlign();
int nbit = (bits + bspos) - 32;
if (bspos >= 32) {
return bufb >> (32 - nbit);
} else if (nbit > 0) {
return ((bufa & (0xffffffff >> bspos)) << nbit) | (bufb >> (32 - nbit));
} else {
return (bufa & (0xffffffff >> bspos)) >> (32 - bspos - bits);
}
}
//---------------------------
/* read n bits from bitstream */
dword Bitstream::GetBits(dword n){
dword ret = ShowBits(n);
Skip(n);
return ret;
}
//---------------------------
static const dword intra_dc_threshold_table[] = {
32, /* never use */
13,
15,
17,
19,
21,
23,
1,
};
//----------------------------
void Bitstream::get_matrix(byte * matrix){
int i = 0;
int last, value = 0;
do {
last = value;
value = GetBits(8);
matrix[scan_tables[0][i++]] = value;
}
while (value != 0 && i < 64);
i--; /* fix little bug at coeff not full */
while (i < 64) {
matrix[scan_tables[0][i++]] = last;
}
}
//----------------------------
/*
* for PVOP addbits == fcode - 1
* for BVOP addbits == max(fcode,bcode) - 1
* returns mbpos
*/
int S_decoder::read_video_packet_header(Bitstream *bs, const int addbits, int *quant, int *fcode_forward, int *fcode_backward, int *intra_dc_threshold){
int startcode_bits = NUMBITS_VP_RESYNC_MARKER + addbits;
int mbnum_bits = log2bin(mb_width * mb_height - 1);
int mbnum;
int hec = 0;
bs->Skip(bs->NumBitsToByteAlign());
bs->Skip(startcode_bits);
DPRINTF(XVID_DEBUG_STARTCODE, "<video_packet_header>\n");
if (shape != VIDOBJLAY_SHAPE_RECTANGULAR)
{
hec = bs->GetBit(); /* header_extension_code */
if (hec && !(sprite_enable == SPRITE_STATIC /* && current_coding_type = I_VOP */))
{
bs->Skip(13); /* vop_width */
READ_MARKER();
bs->Skip(13); /* vop_height */
READ_MARKER();
bs->Skip(13); /* vop_horizontal_mc_spatial_ref */
READ_MARKER();
bs->Skip(13); /* vop_vertical_mc_spatial_ref */
READ_MARKER();
}
}
mbnum = bs->GetBits(mbnum_bits); /* macroblock_number */
DPRINTF(XVID_DEBUG_HEADER, "mbnum %i\n", mbnum);
if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY)
{
*quant = bs->GetBits(quant_bits); /* quant_scale */
DPRINTF(XVID_DEBUG_HEADER, "quant %i\n", *quant);
}
if (shape == VIDOBJLAY_SHAPE_RECTANGULAR)
hec = bs->GetBit(); /* header_extension_code */
DPRINTF(XVID_DEBUG_HEADER, "header_extension_code %i\n", hec);
if (hec)
{
int time_base;
int time_increment = 0;
int coding_type;
for (time_base=0; bs->GetBit()!=0; time_base++); /* modulo_time_base */
READ_MARKER();
if (time_inc_bits)
time_increment = (bs->GetBits(time_inc_bits)); /* vop_time_increment */
READ_MARKER();
//DPRINTF(XVID_DEBUG_HEADER,"time %i:%i\n", time_base, time_increment);
coding_type = bs->GetBits(2);
DPRINTF(XVID_DEBUG_HEADER,"coding_type %i\n", coding_type);
if (shape != VIDOBJLAY_SHAPE_RECTANGULAR)
{
bs->Skip(1); /* change_conv_ratio_disable */
if (coding_type != I_VOP)
bs->Skip(1); /* vop_shape_coding_type */
}
if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY)
{
*intra_dc_threshold = intra_dc_threshold_table[bs->GetBits(3)];
if (sprite_enable == SPRITE_GMC && coding_type == S_VOP &&
sprite_warping_points > 0)
{
/* TODO: sprite trajectory */
}
if(reduced_resolution_enable && shape == VIDOBJLAY_SHAPE_RECTANGULAR && (coding_type == P_VOP || coding_type == I_VOP)){
bs->Skip(1); /* XXX: vop_reduced_resolution */
}
if (coding_type != I_VOP && fcode_forward)
{
*fcode_forward = bs->GetBits(3);
DPRINTF(XVID_DEBUG_HEADER,"fcode_forward %i\n", *fcode_forward);
}
if (coding_type == B_VOP && fcode_backward)
{
*fcode_backward = bs->GetBits(3);
DPRINTF(XVID_DEBUG_HEADER,"fcode_backward %i\n", *fcode_backward);
}
}
}
if (newpred_enable) {
int vop_id;
int vop_id_for_prediction;
vop_id = bs->GetBits(MIN(time_inc_bits + 3, 15));
DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id);
if (bs->GetBit()) /* vop_id_for_prediction_indication */
{
vop_id_for_prediction = bs->GetBits(MIN(time_inc_bits + 3, 15));
DPRINTF(XVID_DEBUG_HEADER, "vop_id_for_prediction %i\n", vop_id_for_prediction);
}
READ_MARKER();
}
return mbnum;
}
//----------------------------
/* vol estimation header */
void S_decoder::read_vol_complexity_estimation_header(Bitstream * bs){
ESTIMATION * e = &estimation;
e->method = bs->GetBits(2); /* estimation_method */
DPRINTF(XVID_DEBUG_HEADER,"+ complexity_estimation_header; method=%i\n", e->method);
if (e->method == 0 || e->method == 1){
if(!bs->GetBit()){
//shape_complexity_estimation_disable
e->opaque = bs->GetBit(); /* opaque */
e->transparent = bs->GetBit(); /* transparent */
e->intra_cae = bs->GetBit(); /* intra_cae */
e->inter_cae = bs->GetBit(); /* inter_cae */
e->no_update = bs->GetBit(); /* no_update */
e->upsampling = bs->GetBit(); /* upsampling */
}
if (!bs->GetBit()) /* texture_complexity_estimation_set_1_disable */
{
e->intra_blocks = bs->GetBit(); /* intra_blocks */
e->inter_blocks = bs->GetBit(); /* inter_blocks */
e->inter4v_blocks = bs->GetBit(); /* inter4v_blocks */
e->not_coded_blocks = bs->GetBit(); /* not_coded_blocks */
}
}
READ_MARKER();
if (!bs->GetBit()){
//texture_complexity_estimation_set_2_disable
e->dct_coefs = bs->GetBit(); /* dct_coefs */
e->dct_lines = bs->GetBit(); /* dct_lines */
e->vlc_symbols = bs->GetBit(); /* vlc_symbols */
e->vlc_bits = bs->GetBit(); /* vlc_bits */
}
if (!bs->GetBit()){
//motion_compensation_complexity_disable
e->apm = bs->GetBit(); /* apm */
e->npm = bs->GetBit(); /* npm */
e->interpolate_mc_q = bs->GetBit(); /* interpolate_mc_q */
e->forw_back_mc_q = bs->GetBit(); /* forw_back_mc_q */
e->halfpel2 = bs->GetBit(); /* halfpel2 */
e->halfpel4 = bs->GetBit(); /* halfpel4 */
}
READ_MARKER();
if (e->method == 1){
if (!bs->GetBit()){
//version2_complexity_estimation_disable
e->sadct = bs->GetBit(); /* sadct */
e->quarterpel = bs->GetBit(); /* quarterpel */
}
}
}
//----------------------------
/* vop estimation header */
void S_decoder::read_vop_complexity_estimation_header(Bitstream * bs, int coding_type){
ESTIMATION * e = &estimation;
if (e->method == 0 || e->method == 1)
{
if (coding_type == I_VOP) {
if (e->opaque) bs->Skip(8); /* dcecs_opaque */
if (e->transparent) bs->Skip(8); /* */
if (e->intra_cae) bs->Skip(8); /* */
if (e->inter_cae) bs->Skip(8); /* */
if (e->no_update) bs->Skip(8); /* */
if (e->upsampling) bs->Skip(8); /* */
if (e->intra_blocks) bs->Skip(8); /* */
if (e->not_coded_blocks) bs->Skip(8); /* */
if (e->dct_coefs) bs->Skip(8); /* */
if (e->dct_lines) bs->Skip(8); /* */
if (e->vlc_symbols) bs->Skip(8); /* */
if (e->vlc_bits) bs->Skip(8); /* */
if (e->sadct) bs->Skip(8); /* */
}
if (coding_type == P_VOP) {
if (e->opaque) bs->Skip(8); /* */
if (e->transparent) bs->Skip(8); /* */
if (e->intra_cae) bs->Skip(8); /* */
if (e->inter_cae) bs->Skip(8); /* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -