📄 bitstream.c
字号:
/*****************************************************************************
*
* 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.c,v 1.57 2007/04/16 19:01:28 Skal Exp $
*
****************************************************************************/
#include <string.h>
#include <stdio.h>
#include "bitstream.h"
#include "zigzag.h"
#include "../quant/quant_matrix.h"
#include "mbcoding.h"
static const uint8_t log2_tab_16[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
static uint32_t __inline log2bin(uint32_t value)
{
int n = 0;
if (value & 0xffff0000) {
value >>= 16;
n += 16;
}
if (value & 0xff00) {
value >>= 8;
n += 8;
}
if (value & 0xf0) {
value >>= 4;
n += 4;
}
return n + log2_tab_16[value];
}
static const uint32_t intra_dc_threshold_table[] = {
32, /* never use */
13,
15,
17,
19,
21,
23,
1,
};
static void
bs_get_matrix(Bitstream * bs,
uint8_t * matrix)
{
int i = 0;
int last, value = 0;
do {
last = value;
value = BitstreamGetBits(bs, 8);
matrix[scan_tables[0][i++]] = value;
}
while (value != 0 && i < 64);
if (value != 0) return;
i--;
while (i < 64) {
matrix[scan_tables[0][i++]] = last;
}
}
/*
* for PVOP addbits == fcode - 1
* for BVOP addbits == max(fcode,bcode) - 1
* returns mbpos
*/
int
read_video_packet_header(Bitstream *bs,
DECODER * dec,
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(dec->mb_width * dec->mb_height - 1);
int mbnum;
int hec = 0;
BitstreamSkip(bs, BitstreamNumBitsToByteAlign(bs));
BitstreamSkip(bs, startcode_bits);
DPRINTF(XVID_DEBUG_STARTCODE, "<video_packet_header>\n");
if (dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR)
{
hec = BitstreamGetBit(bs); /* header_extension_code */
if (hec && !(dec->sprite_enable == SPRITE_STATIC /* && current_coding_type = I_VOP */))
{
BitstreamSkip(bs, 13); /* vop_width */
READ_MARKER();
BitstreamSkip(bs, 13); /* vop_height */
READ_MARKER();
BitstreamSkip(bs, 13); /* vop_horizontal_mc_spatial_ref */
READ_MARKER();
BitstreamSkip(bs, 13); /* vop_vertical_mc_spatial_ref */
READ_MARKER();
}
}
mbnum = BitstreamGetBits(bs, mbnum_bits); /* macroblock_number */
DPRINTF(XVID_DEBUG_HEADER, "mbnum %i\n", mbnum);
if (dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY)
{
*quant = BitstreamGetBits(bs, dec->quant_bits); /* quant_scale */
DPRINTF(XVID_DEBUG_HEADER, "quant %i\n", *quant);
}
if (dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR)
hec = BitstreamGetBit(bs); /* header_extension_code */
DPRINTF(XVID_DEBUG_HEADER, "header_extension_code %i\n", hec);
if (hec)
{
int time_base;
int time_increment;
int coding_type;
for (time_base=0; BitstreamGetBit(bs)!=0; time_base++); /* modulo_time_base */
READ_MARKER();
if (dec->time_inc_bits)
time_increment = (BitstreamGetBits(bs, dec->time_inc_bits)); /* vop_time_increment */
READ_MARKER();
DPRINTF(XVID_DEBUG_HEADER,"time %i:%i\n", time_base, time_increment);
coding_type = BitstreamGetBits(bs, 2);
DPRINTF(XVID_DEBUG_HEADER,"coding_type %i\n", coding_type);
if (dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR)
{
BitstreamSkip(bs, 1); /* change_conv_ratio_disable */
if (coding_type != I_VOP)
BitstreamSkip(bs, 1); /* vop_shape_coding_type */
}
if (dec->shape != VIDOBJLAY_SHAPE_BINARY_ONLY)
{
*intra_dc_threshold = intra_dc_threshold_table[BitstreamGetBits(bs, 3)];
if (dec->sprite_enable == SPRITE_GMC && coding_type == S_VOP &&
dec->sprite_warping_points > 0)
{
/* TODO: sprite trajectory */
}
if (dec->reduced_resolution_enable &&
dec->shape == VIDOBJLAY_SHAPE_RECTANGULAR &&
(coding_type == P_VOP || coding_type == I_VOP))
{
BitstreamSkip(bs, 1); /* XXX: vop_reduced_resolution */
}
if (coding_type != I_VOP && fcode_forward)
{
*fcode_forward = BitstreamGetBits(bs, 3);
DPRINTF(XVID_DEBUG_HEADER,"fcode_forward %i\n", *fcode_forward);
}
if (coding_type == B_VOP && fcode_backward)
{
*fcode_backward = BitstreamGetBits(bs, 3);
DPRINTF(XVID_DEBUG_HEADER,"fcode_backward %i\n", *fcode_backward);
}
}
}
if (dec->newpred_enable)
{
int vop_id;
int vop_id_for_prediction;
vop_id = BitstreamGetBits(bs, MIN(dec->time_inc_bits + 3, 15));
DPRINTF(XVID_DEBUG_HEADER, "vop_id %i\n", vop_id);
if (BitstreamGetBit(bs)) /* vop_id_for_prediction_indication */
{
vop_id_for_prediction = BitstreamGetBits(bs, MIN(dec->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 */
static void
read_vol_complexity_estimation_header(Bitstream * bs, DECODER * dec)
{
ESTIMATION * e = &dec->estimation;
e->method = BitstreamGetBits(bs, 2); /* estimation_method */
DPRINTF(XVID_DEBUG_HEADER,"+ complexity_estimation_header; method=%i\n", e->method);
if (e->method == 0 || e->method == 1)
{
if (!BitstreamGetBit(bs)) /* shape_complexity_estimation_disable */
{
e->opaque = BitstreamGetBit(bs); /* opaque */
e->transparent = BitstreamGetBit(bs); /* transparent */
e->intra_cae = BitstreamGetBit(bs); /* intra_cae */
e->inter_cae = BitstreamGetBit(bs); /* inter_cae */
e->no_update = BitstreamGetBit(bs); /* no_update */
e->upsampling = BitstreamGetBit(bs); /* upsampling */
}
if (!BitstreamGetBit(bs)) /* texture_complexity_estimation_set_1_disable */
{
e->intra_blocks = BitstreamGetBit(bs); /* intra_blocks */
e->inter_blocks = BitstreamGetBit(bs); /* inter_blocks */
e->inter4v_blocks = BitstreamGetBit(bs); /* inter4v_blocks */
e->not_coded_blocks = BitstreamGetBit(bs); /* not_coded_blocks */
}
}
READ_MARKER();
if (!BitstreamGetBit(bs)) /* texture_complexity_estimation_set_2_disable */
{
e->dct_coefs = BitstreamGetBit(bs); /* dct_coefs */
e->dct_lines = BitstreamGetBit(bs); /* dct_lines */
e->vlc_symbols = BitstreamGetBit(bs); /* vlc_symbols */
e->vlc_bits = BitstreamGetBit(bs); /* vlc_bits */
}
if (!BitstreamGetBit(bs)) /* motion_compensation_complexity_disable */
{
e->apm = BitstreamGetBit(bs); /* apm */
e->npm = BitstreamGetBit(bs); /* npm */
e->interpolate_mc_q = BitstreamGetBit(bs); /* interpolate_mc_q */
e->forw_back_mc_q = BitstreamGetBit(bs); /* forw_back_mc_q */
e->halfpel2 = BitstreamGetBit(bs); /* halfpel2 */
e->halfpel4 = BitstreamGetBit(bs); /* halfpel4 */
}
READ_MARKER();
if (e->method == 1)
{
if (!BitstreamGetBit(bs)) /* version2_complexity_estimation_disable */
{
e->sadct = BitstreamGetBit(bs); /* sadct */
e->quarterpel = BitstreamGetBit(bs); /* quarterpel */
}
}
}
/* vop estimation header */
static void
read_vop_complexity_estimation_header(Bitstream * bs, DECODER * dec, int coding_type)
{
ESTIMATION * e = &dec->estimation;
if (e->method == 0 || e->method == 1)
{
if (coding_type == I_VOP) {
if (e->opaque) BitstreamSkip(bs, 8); /* dcecs_opaque */
if (e->transparent) BitstreamSkip(bs, 8); /* */
if (e->intra_cae) BitstreamSkip(bs, 8); /* */
if (e->inter_cae) BitstreamSkip(bs, 8); /* */
if (e->no_update) BitstreamSkip(bs, 8); /* */
if (e->upsampling) BitstreamSkip(bs, 8); /* */
if (e->intra_blocks) BitstreamSkip(bs, 8); /* */
if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */
if (e->dct_coefs) BitstreamSkip(bs, 8); /* */
if (e->dct_lines) BitstreamSkip(bs, 8); /* */
if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */
if (e->vlc_bits) BitstreamSkip(bs, 8); /* */
if (e->sadct) BitstreamSkip(bs, 8); /* */
}
if (coding_type == P_VOP) {
if (e->opaque) BitstreamSkip(bs, 8); /* */
if (e->transparent) BitstreamSkip(bs, 8); /* */
if (e->intra_cae) BitstreamSkip(bs, 8); /* */
if (e->inter_cae) BitstreamSkip(bs, 8); /* */
if (e->no_update) BitstreamSkip(bs, 8); /* */
if (e->upsampling) BitstreamSkip(bs, 8); /* */
if (e->intra_blocks) BitstreamSkip(bs, 8); /* */
if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */
if (e->dct_coefs) BitstreamSkip(bs, 8); /* */
if (e->dct_lines) BitstreamSkip(bs, 8); /* */
if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */
if (e->vlc_bits) BitstreamSkip(bs, 8); /* */
if (e->inter_blocks) BitstreamSkip(bs, 8); /* */
if (e->inter4v_blocks) BitstreamSkip(bs, 8); /* */
if (e->apm) BitstreamSkip(bs, 8); /* */
if (e->npm) BitstreamSkip(bs, 8); /* */
if (e->forw_back_mc_q) BitstreamSkip(bs, 8); /* */
if (e->halfpel2) BitstreamSkip(bs, 8); /* */
if (e->halfpel4) BitstreamSkip(bs, 8); /* */
if (e->sadct) BitstreamSkip(bs, 8); /* */
if (e->quarterpel) BitstreamSkip(bs, 8); /* */
}
if (coding_type == B_VOP) {
if (e->opaque) BitstreamSkip(bs, 8); /* */
if (e->transparent) BitstreamSkip(bs, 8); /* */
if (e->intra_cae) BitstreamSkip(bs, 8); /* */
if (e->inter_cae) BitstreamSkip(bs, 8); /* */
if (e->no_update) BitstreamSkip(bs, 8); /* */
if (e->upsampling) BitstreamSkip(bs, 8); /* */
if (e->intra_blocks) BitstreamSkip(bs, 8); /* */
if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */
if (e->dct_coefs) BitstreamSkip(bs, 8); /* */
if (e->dct_lines) BitstreamSkip(bs, 8); /* */
if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */
if (e->vlc_bits) BitstreamSkip(bs, 8); /* */
if (e->inter_blocks) BitstreamSkip(bs, 8); /* */
if (e->inter4v_blocks) BitstreamSkip(bs, 8); /* */
if (e->apm) BitstreamSkip(bs, 8); /* */
if (e->npm) BitstreamSkip(bs, 8); /* */
if (e->forw_back_mc_q) BitstreamSkip(bs, 8); /* */
if (e->halfpel2) BitstreamSkip(bs, 8); /* */
if (e->halfpel4) BitstreamSkip(bs, 8); /* */
if (e->interpolate_mc_q) BitstreamSkip(bs, 8); /* */
if (e->sadct) BitstreamSkip(bs, 8); /* */
if (e->quarterpel) BitstreamSkip(bs, 8); /* */
}
if (coding_type == S_VOP && dec->sprite_enable == SPRITE_STATIC) {
if (e->intra_blocks) BitstreamSkip(bs, 8); /* */
if (e->not_coded_blocks) BitstreamSkip(bs, 8); /* */
if (e->dct_coefs) BitstreamSkip(bs, 8); /* */
if (e->dct_lines) BitstreamSkip(bs, 8); /* */
if (e->vlc_symbols) BitstreamSkip(bs, 8); /* */
if (e->vlc_bits) BitstreamSkip(bs, 8); /* */
if (e->inter_blocks) BitstreamSkip(bs, 8); /* */
if (e->inter4v_blocks) BitstreamSkip(bs, 8); /* */
if (e->apm) BitstreamSkip(bs, 8); /* */
if (e->npm) BitstreamSkip(bs, 8); /* */
if (e->forw_back_mc_q) BitstreamSkip(bs, 8); /* */
if (e->halfpel2) BitstreamSkip(bs, 8); /* */
if (e->halfpel4) BitstreamSkip(bs, 8); /* */
if (e->interpolate_mc_q) BitstreamSkip(bs, 8); /* */
}
}
}
/*
decode headers
returns coding_type, or -1 if error
*/
#define VIDOBJ_START_CODE_MASK 0x0000001f
#define VIDOBJLAY_START_CODE_MASK 0x0000000f
int
BitstreamReadHeaders(Bitstream * bs,
DECODER * dec,
uint32_t * rounding,
uint32_t * quant,
uint32_t * fcode_forward,
uint32_t * fcode_backward,
uint32_t * intra_dc_threshold,
WARPPOINTS *gmc_warp)
{
uint32_t vol_ver_id;
uint32_t coding_type;
uint32_t start_code;
uint32_t time_incr = 0;
int32_t time_increment = 0;
int resize = 0;
while ((BitstreamPos(bs) >> 3) + 4 <= bs->length) {
BitstreamByteAlign(bs);
start_code = BitstreamShowBits(bs, 32);
if (start_code == VISOBJSEQ_START_CODE) {
int profile;
DPRINTF(XVID_DEBUG_STARTCODE, "<visual_object_sequence>\n");
BitstreamSkip(bs, 32); /* visual_object_sequence_start_code */
profile = BitstreamGetBits(bs, 8); /* profile_and_level_indication */
DPRINTF(XVID_DEBUG_HEADER, "profile_and_level_indication %i\n", profile);
} else if (start_code == VISOBJSEQ_STOP_CODE) {
BitstreamSkip(bs, 32); /* visual_object_sequence_stop_code */
DPRINTF(XVID_DEBUG_STARTCODE, "</visual_object_sequence>\n");
} else if (start_code == VISOBJ_START_CODE) {
DPRINTF(XVID_DEBUG_STARTCODE, "<visual_object>\n");
BitstreamSkip(bs, 32); /* visual_object_start_code */
if (BitstreamGetBit(bs)) /* is_visual_object_identified */
{
dec->ver_id = BitstreamGetBits(bs, 4); /* visual_object_ver_id */
DPRINTF(XVID_DEBUG_HEADER,"visobj_ver_id %i\n", dec->ver_id);
BitstreamSkip(bs, 3); /* visual_object_priority */
} else {
dec->ver_id = 1;
}
if (BitstreamShowBits(bs, 4) != VISOBJ_TYPE_VIDEO) /* visual_object_type */
{
DPRINTF(XVID_DEBUG_ERROR, "visual_object_type != video\n");
return -1;
}
BitstreamSkip(bs, 4);
/* video_signal_type */
if (BitstreamGetBit(bs)) /* video_signal_type */
{
DPRINTF(XVID_DEBUG_HEADER,"+ video_signal_type\n");
BitstreamSkip(bs, 3); /* video_format */
BitstreamSkip(bs, 1); /* video_range */
if (BitstreamGetBit(bs)) /* color_description */
{
DPRINTF(XVID_DEBUG_HEADER,"+ color_description");
BitstreamSkip(bs, 8); /* color_primaries */
BitstreamSkip(bs, 8); /* transfer_characteristics */
BitstreamSkip(bs, 8); /* matrix_coefficients */
}
}
} else if ((start_code & ~VIDOBJ_START_CODE_MASK) == VIDOBJ_START_CODE) {
DPRINTF(XVID_DEBUG_STARTCODE, "<video_object>\n");
DPRINTF(XVID_DEBUG_HEADER, "vo id %i\n", start_code & VIDOBJ_START_CODE_MASK);
BitstreamSkip(bs, 32); /* video_object_start_code */
} else if ((start_code & ~VIDOBJLAY_START_CODE_MASK) == VIDOBJLAY_START_CODE) {
DPRINTF(XVID_DEBUG_STARTCODE, "<video_object_layer>\n");
DPRINTF(XVID_DEBUG_HEADER, "vol id %i\n", start_code & VIDOBJLAY_START_CODE_MASK);
BitstreamSkip(bs, 32); /* video_object_layer_start_code */
BitstreamSkip(bs, 1); /* random_accessible_vol */
BitstreamSkip(bs, 8); /* video_object_type_indication */
if (BitstreamGetBit(bs)) /* is_object_layer_identifier */
{
DPRINTF(XVID_DEBUG_HEADER, "+ is_object_layer_identifier\n");
vol_ver_id = BitstreamGetBits(bs, 4); /* video_object_layer_verid */
DPRINTF(XVID_DEBUG_HEADER,"ver_id %i\n", vol_ver_id);
BitstreamSkip(bs, 3); /* video_object_layer_priority */
} else {
vol_ver_id = dec->ver_id;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -