📄 bitstream.c
字号:
/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
This library 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 Lesser General Public License for
more details.
**********/
#include "bitstream.h"
#include <stdio.h>
#include <memory.h>
#include <stdlib.h> /* For _MAX_PATH definition */
#include <malloc.h>
/////////////////////////////////////
uint32_t *bitstream;
///////////////////////
/* reads n bits from bitstream without changing the stream pos */
uint32_t BitstreamShowBits(Bitstream * bs,uint32_t bits)
{
int nbit = (bits + bs->pos) - 32;
uint32_t ret_value;
if (nbit > 0)
{
ret_value = ((bs->bufa & (0xffffffff >> bs->pos)) << nbit) |
(bs->bufb >> (32 - nbit));
}
else
{
ret_value = (bs->bufa & (0xffffffff >> bs->pos)) >> (32 - bs->pos - bits);
}
// fprintf(stderr,"show 2 bufa :%x; bufb :%x ;pos :%u;\n",bs->bufa,bs->bufb,bs->pos);
// fprintf(stderr,"showbits %d %x\n", bits, ret_value);
return ret_value;
}
/* skip n bits forward in bitstream */
void BitstreamSkip(Bitstream * bs,uint32_t bits)
{
uint32_t tmp;
bs->pos += bits;
if (bs->pos >= 32)
{
bs->bufa = bs->bufb;
tmp = *((uint32_t *)bs->tail + 2);
bs->bufb = tmp;
bs->tail++;
bs->pos -= 32;
}
// fprintf(stderr,"skip 2 bufa :%x; bufb :%x ;pos :%u;\n",bs->bufa,bs->bufb,bs->pos);
//fprintf(stderr,"used %d\n", bits);
}
/* bitstream length (unit bits) */
uint32_t BitstreamPos(Bitstream * bs)
{
return 8 * ((uint32_t)bs->tail - (uint32_t)bs->start) + bs->pos;
}
/* flush the bitstream & return length (unit bytes)
NOTE: assumes no futher bitstream functions will be called.
*/
uint32_t BitstreamLength(Bitstream * bs)
{
uint32_t len = (uint32_t) bs->tail - (uint32_t) bs->start;
uint32_t b;
if (bs->pos)
{
b = bs->buf;
*bs->tail = b;
len += (bs->pos + 7) / 8;
}
return len;
}
/* read n bits from bitstream */
uint32_t BitstreamGetBits(Bitstream * bs,uint32_t n)
{
uint32_t ret = BitstreamShowBits(bs, n);
BitstreamSkip(bs, n);
return ret;
}
/* read single bit from bitstream */
uint32_t BitstreamGetBit(Bitstream * const bs)
{
return BitstreamGetBits(bs, 1);
}
////////////////////////////////////
int log2bin(int value)
{
int n = 0;
while (value)
{
value >>= 1;
n++;
}
return n;
}
static const uint32_t intra_dc_threshold_table[] =
{
32, /* never use */
13,
15,
17,
19,
21,
23,
1,
};
////////////////////////////
void BitstreamByteAlign(Bitstream *bs)
{
uint32_t remainder = bs->pos % 8;
if (remainder)
{
BitstreamSkip(bs, 8 - remainder);
}
}
/*
decode headers
returns coding_type, or -1 if error
*/
int BitstreamReadHeaders(Bitstream * bs, XVID_DEC_PARAM * param,int findvol)
{
uint32_t rounding;
uint32_t quant;
uint32_t fcode;
uint32_t intra_dc_threshold;
static uint32_t vol_ver_id = 0;
static uint32_t time_inc_resolution = 0;
static uint32_t time_inc_bits = 0;
static uint32_t coding_type = 0;
static uint32_t fixed_vop_time_increment = 0;
uint32_t start_code;
static uint32_t width = 0, height = 0;
static uint32_t shape = 0;
static uint32_t interlacing = 0;
static uint32_t top_field_first = 0;
static uint32_t alternate_vertical_scan = 0;
static uint32_t quant_bits = 0;
static uint32_t quant_type = 0;
static uint32_t quarterpel = 0;
static uint32_t have_short_header = 0;
int hours, minutes, seconds;
uint32_t temp_width=0, temp_height=0;
uint32_t horiz_mc_ref, vert_mc_ref;
uint32_t source_format;
do
{
BitstreamByteAlign(bs);
start_code = BitstreamShowBits(bs, 32);
// fprintf(stderr,"1 start_code is %x\n",start_code);
//BitstreamSkip(bs,32);
if (start_code == VISOBJSEQ_START_CODE)
{
BitstreamSkip(bs, 32); // visual_object_sequence_start_code
BitstreamSkip(bs, 8); // profile_and_level_indication
}
else if (start_code == VISOBJSEQ_STOP_CODE)
{
BitstreamSkip(bs, 32); // visual_object_sequence_stop_code
}
else if (start_code == VISOBJ_START_CODE)
{
BitstreamSkip(bs,32); // visual_object_start_code
if (BitstreamGetBit(bs)) // is_visual_object_identified
{
vol_ver_id = BitstreamGetBits(bs,4); // visual_object_ver_id
BitstreamSkip(bs, 3); // visual_object_priority
}
else
{
vol_ver_id = 1;
}
if (BitstreamShowBits(bs, 4) != VISOBJ_TYPE_VIDEO) // visual_object_type
{
// DEBUG("visual_object_type != video");
return -1;
}
BitstreamSkip(bs, 4);
// video_signal_type
if (BitstreamGetBit(bs)) // video_signal_type
{
// DEBUG("+ video_signal_type");
BitstreamSkip(bs, 3); // video_format
BitstreamSkip(bs, 1); // video_range
if (BitstreamGetBit(bs)) // color_description
{
// DEBUG("+ color_description");
BitstreamSkip(bs, 8); // color_primaries
BitstreamSkip(bs, 8); // transfer_characteristics
BitstreamSkip(bs, 8); // matrix_coefficients
}
}
}
else if ((start_code & ~0x1f) == VIDOBJ_START_CODE)
{
fprintf(stderr,"video_object_start_code \n");
BitstreamSkip(bs, 32); // video_object_start_code
}
else if ((start_code & ~0xf) == VIDOBJLAY_START_CODE)
{
// DEBUG("video_object_layer");
BitstreamSkip(bs, 32); // video_object_layer_start_code
BitstreamSkip(bs, 1); // random_accessible_vol
// video_object_type_indication
if (BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_SIMPLE &&
BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_CORE &&
BitstreamShowBits(bs, 8) != VIDOBJLAY_TYPE_MAIN &&
BitstreamShowBits(bs, 8) != 0) // BUGGY DIVX
{
// DEBUG1("video_object_type_indication not supported", BitstreamShowBits(bs, 8));
fprintf(stderr,"video_object_type_indication not supported %d\n", BitstreamShowBits(bs, 8));
return -1;
}
BitstreamSkip(bs, 8);
if (BitstreamGetBit(bs)) // is_object_layer_identifier
{
//DEBUG("+ is_object_layer_identifier");
vol_ver_id = BitstreamGetBits(bs,4); // video_object_layer_verid
BitstreamSkip(bs, 3); // video_object_layer_priority
}
else
{
vol_ver_id = 1;
}
//DEBUGI("vol_ver_id", vol_ver_id);
if (BitstreamGetBits(bs, 4) == VIDOBJLAY_AR_EXTPAR) // aspect_ratio_info
{
//DEBUG("+ aspect_ratio_info");
BitstreamSkip(bs, 8); // par_width
BitstreamSkip(bs, 8); // par_height
}
if (BitstreamGetBit(bs)) // vol_control_parameters
{
//DEBUG("+ vol_control_parameters");
BitstreamSkip(bs, 2); // chroma_format
BitstreamSkip(bs, 1); // low_delay
if (BitstreamGetBit(bs)) // vbv_parameters
{
//DEBUG("+ vbv_parameters");
BitstreamSkip(bs, 15); // first_half_bitrate
READ_MARKER();
BitstreamSkip(bs, 15); // latter_half_bitrate
READ_MARKER();
BitstreamSkip(bs, 15); // first_half_vbv_buffer_size
READ_MARKER();
BitstreamSkip(bs, 3); // latter_half_vbv_buffer_size
BitstreamSkip(bs, 11); // first_half_vbv_occupancy
READ_MARKER();
BitstreamSkip(bs, 15); // latter_half_vbv_occupancy
READ_MARKER();
}
}
shape = BitstreamGetBits(bs, 2); // video_object_layer_shape
// DEBUG1("shape", dec->shape);
if (shape == VIDOBJLAY_SHAPE_GRAYSCALE && vol_ver_id != 1)
{
BitstreamSkip(bs, 4); // video_object_layer_shape_extension
}
READ_MARKER();
time_inc_resolution = BitstreamGetBits(bs, 16); // vop_time_increment_resolution
//time_inc_resolution--;
fprintf(stderr,"time_inc_resolution is %u\n",time_inc_resolution);
if (time_inc_resolution > 0)
{
time_inc_bits = log2bin(time_inc_resolution);
}
else
{
// dec->time_inc_bits = 0;
// for "old" xvid compatibility, set time_inc_bits = 1
time_inc_bits = 1;
}
READ_MARKER();
if (BitstreamGetBit(bs)) // fixed_vop_rate
{
//BitstreamSkip(bs, time_inc_bits); // fixed_vop_time_increment
fixed_vop_time_increment = BitstreamGetBits(bs, time_inc_bits); // fixed_vop_time_increment
param->framerate = time_inc_resolution*1000/fixed_vop_time_increment;
fixed_vop_rate = 1;
}
else
{
param->framerate = time_inc_resolution*1000/1001;
}
if (shape != VIDOBJLAY_SHAPE_BINARY_ONLY)
{
if (shape == VIDOBJLAY_SHAPE_RECTANGULAR)
{
READ_MARKER();
temp_width = BitstreamGetBits(bs, 13); // video_object_layer_width
//DEBUGI("width", width);
//fprintf(stderr,"width is %u\n",width);
READ_MARKER();
temp_height = BitstreamGetBits(bs, 13); // video_object_layer_height
//DEBUGI("height", height);
//fprintf(stderr,"height is %u\n",height);
READ_MARKER();
if (findvol == 0)
{
if (temp_width != width || temp_height != height)
{
fprintf(stderr,"FATAL: video dimension discrepancy ***");
fprintf(stderr,"bitstream width %u /height %u\n", temp_width, temp_height);
fprintf(stderr,"param width %u /height %u\n", width, height);
return -1;
}
}
else
{
width = temp_width;
height = temp_height;
}
}
if ((interlacing = BitstreamGetBit(bs)))
{
fprintf(stderr,"vol: interlacing\n");
}
if (!BitstreamGetBit(bs)) // obmc_disable
{
fprintf(stderr,"IGNORED/TODO: !obmc_disable\n");
// TODO
// fucking divx4.02 has this enabled
}
if (BitstreamGetBits(bs, (vol_ver_id == 1 ? 1 : 2))) // sprite_enable
{
fprintf(stderr,"sprite_enable; not supported\n");
return -1;
}
if (vol_ver_id != 1 && shape != VIDOBJLAY_SHAPE_RECTANGULAR)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -