📄 bitstream.c
字号:
DPRINTF(XVID_DEBUG_HEADER, "fcode_backward %i\n", *fcode_backward);
}
if (!dec->scalability) {
if ((dec->shape != VIDOBJLAY_SHAPE_RECTANGULAR) &&
(coding_type != I_VOP)) {
BitstreamSkip(bs, 1); /* vop_shape_coding_type */
}
}
return coding_type;
} else if (start_code == USERDATA_START_CODE) {
char tmp[256];
int i, version, build;
char packed;
BitstreamSkip(bs, 32); /* user_data_start_code */
memset(tmp, 0, 256);
tmp[0] = BitstreamShowBits(bs, 8);
for(i = 1; i < 256; i++){
tmp[i] = (BitstreamShowBits(bs, 16) & 0xFF);
if(tmp[i] == 0)
break;
BitstreamSkip(bs, 8);
}
DPRINTF(XVID_DEBUG_STARTCODE, "<user_data>: %s\n", tmp);
/* read xvid bitstream version */
if(strncmp(tmp, "XviD", 4) == 0) {
if (tmp[strlen(tmp)-1] == 'C') {
sscanf(tmp, "XviD%dC", &dec->bs_version);
dec->cartoon_mode = 1;
}
else
sscanf(tmp, "XviD%d", &dec->bs_version);
DPRINTF(XVID_DEBUG_HEADER, "xvid bitstream version=%i\n", dec->bs_version);
}
/* divx detection */
i = sscanf(tmp, "DivX%dBuild%d%c", &version, &build, &packed);
if (i < 2)
i = sscanf(tmp, "DivX%db%d%c", &version, &build, &packed);
if (i >= 2)
{
dec->packed_mode = (i == 3 && packed == 'p');
DPRINTF(XVID_DEBUG_HEADER, "divx version=%i, build=%i packed=%i\n",
version, build, dec->packed_mode);
}
} else /* start_code == ? */
{
if (BitstreamShowBits(bs, 24) == 0x000001) {
DPRINTF(XVID_DEBUG_STARTCODE, "<unknown: %x>\n", BitstreamShowBits(bs, 32));
}
BitstreamSkip(bs, 8);
}
}
#if 0
DPRINTF("*** WARNING: no vop_start_code found");
#endif
return -1; /* ignore it */
}
/* write custom quant matrix */
static void
bs_put_matrix(Bitstream * bs,
const uint16_t * matrix)
{
int i, j;
const int last = matrix[scan_tables[0][63]];
for (j = 63; j > 0 && matrix[scan_tables[0][j - 1]] == last; j--);
for (i = 0; i <= j; i++) {
BitstreamPutBits(bs, matrix[scan_tables[0][i]], 8);
}
if (j < 63) {
BitstreamPutBits(bs, 0, 8);
}
}
/*
write vol header
*/
void
BitstreamWriteVolHeader(Bitstream * const bs,
const MBParam * pParam,
const FRAMEINFO * const frame)
{
static const unsigned int vo_id = 0;
static const unsigned int vol_id = 0;
int vol_ver_id = 1;
int vol_type_ind = VIDOBJLAY_TYPE_SIMPLE;
int vol_profile = pParam->profile;
if ( (pParam->vol_flags & XVID_VOL_QUARTERPEL) ||
(pParam->vol_flags & XVID_VOL_GMC))
vol_ver_id = 2;
if ((pParam->vol_flags & (XVID_VOL_MPEGQUANT|XVID_VOL_QUARTERPEL|XVID_VOL_GMC|XVID_VOL_INTERLACING)) ||
pParam->max_bframes>0) {
vol_type_ind = VIDOBJLAY_TYPE_ASP;
}
/* visual_object_sequence_start_code */
#if 0
BitstreamPad(bs);
#endif
/*
* no padding here, anymore. You have to make sure that you are
* byte aligned, and that always 1-8 padding bits have been written
*/
if (!vol_profile) {
/* Profile was not set by client app, use the more permissive profile
* compatible with the vol_type_id */
switch(vol_type_ind) {
case VIDOBJLAY_TYPE_ASP:
vol_profile = 0xf5; /* ASP level 5 */
break;
case VIDOBJLAY_TYPE_ART_SIMPLE:
vol_profile = 0x94; /* ARTS level 4 */
break;
default:
vol_profile = 0x03; /* Simple level 3 */
break;
}
}
/* Write the VOS header */
BitstreamPutBits(bs, VISOBJSEQ_START_CODE, 32);
BitstreamPutBits(bs, vol_profile, 8); /* profile_and_level_indication */
/* visual_object_start_code */
BitstreamPad(bs);
BitstreamPutBits(bs, VISOBJ_START_CODE, 32);
BitstreamPutBits(bs, 0, 1); /* is_visual_object_identifier */
/* Video type */
BitstreamPutBits(bs, VISOBJ_TYPE_VIDEO, 4); /* visual_object_type */
BitstreamPutBit(bs, 0); /* video_signal_type */
/* video object_start_code & vo_id */
BitstreamPadAlways(bs); /* next_start_code() */
BitstreamPutBits(bs, VIDOBJ_START_CODE|(vo_id&0x5), 32);
/* video_object_layer_start_code & vol_id */
BitstreamPad(bs);
BitstreamPutBits(bs, VIDOBJLAY_START_CODE|(vol_id&0x4), 32);
BitstreamPutBit(bs, 0); /* random_accessible_vol */
BitstreamPutBits(bs, vol_type_ind, 8); /* video_object_type_indication */
if (vol_ver_id == 1) {
BitstreamPutBit(bs, 0); /* is_object_layer_identified (0=not given) */
} else {
BitstreamPutBit(bs, 1); /* is_object_layer_identified */
BitstreamPutBits(bs, vol_ver_id, 4); /* vol_ver_id == 2 */
BitstreamPutBits(bs, 4, 3); /* vol_ver_priority (1==highest, 7==lowest) */
}
/* Aspect ratio */
BitstreamPutBits(bs, pParam->par, 4); /* aspect_ratio_info (1=1:1) */
if(pParam->par == XVID_PAR_EXT) {
BitstreamPutBits(bs, pParam->par_width, 8);
BitstreamPutBits(bs, pParam->par_height, 8);
}
BitstreamPutBit(bs, 1); /* vol_control_parameters */
BitstreamPutBits(bs, 1, 2); /* chroma_format 1="4:2:0" */
if (pParam->max_bframes > 0) {
BitstreamPutBit(bs, 0); /* low_delay */
} else
{
BitstreamPutBit(bs, 1); /* low_delay */
}
BitstreamPutBit(bs, 0); /* vbv_parameters (0=not given) */
BitstreamPutBits(bs, 0, 2); /* video_object_layer_shape (0=rectangular) */
WRITE_MARKER();
/*
* time_inc_resolution; ignored by current decore versions
* eg. 2fps res=2 inc=1
* 25fps res=25 inc=1
* 29.97fps res=30000 inc=1001
*/
BitstreamPutBits(bs, pParam->fbase, 16);
WRITE_MARKER();
if (pParam->fincr>0) {
BitstreamPutBit(bs, 1); /* fixed_vop_rate = 1 */
BitstreamPutBits(bs, pParam->fincr, MAX(log2bin(pParam->fbase-1),1)); /* fixed_vop_time_increment */
}else{
BitstreamPutBit(bs, 0); /* fixed_vop_rate = 0 */
}
WRITE_MARKER();
BitstreamPutBits(bs, pParam->width, 13); /* width */
WRITE_MARKER();
BitstreamPutBits(bs, pParam->height, 13); /* height */
WRITE_MARKER();
BitstreamPutBit(bs, pParam->vol_flags & XVID_VOL_INTERLACING); /* interlace */
BitstreamPutBit(bs, 1); /* obmc_disable (overlapped block motion compensation) */
if (vol_ver_id != 1)
{ if ((pParam->vol_flags & XVID_VOL_GMC))
{ BitstreamPutBits(bs, 2, 2); /* sprite_enable=='GMC' */
BitstreamPutBits(bs, 3, 6); /* no_of_sprite_warping_points */
BitstreamPutBits(bs, 3, 2); /* sprite_warping_accuracy 0==1/2, 1=1/4, 2=1/8, 3=1/16 */
BitstreamPutBit(bs, 0); /* sprite_brightness_change (not supported) */
/*
* currently we use no_of_sprite_warping_points==2, sprite_warping_accuracy==3
* for DivX5 compatability
*/
} else
BitstreamPutBits(bs, 0, 2); /* sprite_enable==off */
}
else
BitstreamPutBit(bs, 0); /* sprite_enable==off */
BitstreamPutBit(bs, 0); /* not_8_bit */
/* quant_type 0=h.263 1=mpeg4(quantizer tables) */
BitstreamPutBit(bs, pParam->vol_flags & XVID_VOL_MPEGQUANT);
if ((pParam->vol_flags & XVID_VOL_MPEGQUANT)) {
BitstreamPutBit(bs, is_custom_intra_matrix(pParam->mpeg_quant_matrices)); /* load_intra_quant_mat */
if(is_custom_intra_matrix(pParam->mpeg_quant_matrices))
bs_put_matrix(bs, get_intra_matrix(pParam->mpeg_quant_matrices));
BitstreamPutBit(bs, is_custom_inter_matrix(pParam->mpeg_quant_matrices)); /* load_inter_quant_mat */
if(is_custom_inter_matrix(pParam->mpeg_quant_matrices))
bs_put_matrix(bs, get_inter_matrix(pParam->mpeg_quant_matrices));
}
if (vol_ver_id != 1) {
if ((pParam->vol_flags & XVID_VOL_QUARTERPEL))
BitstreamPutBit(bs, 1); /* quarterpel */
else
BitstreamPutBit(bs, 0); /* no quarterpel */
}
BitstreamPutBit(bs, 1); /* complexity_estimation_disable */
BitstreamPutBit(bs, 1); /* resync_marker_disable */
BitstreamPutBit(bs, 0); /* data_partitioned */
if (vol_ver_id != 1) {
BitstreamPutBit(bs, 0); /* newpred_enable */
BitstreamPutBit(bs, 0); /* reduced_resolution_vop_enabled */
}
BitstreamPutBit(bs, 0); /* scalability */
BitstreamPadAlways(bs); /* next_start_code(); */
/* divx5 userdata string */
#define DIVX5_ID ((char *)"DivX503b1393")
if ((pParam->global_flags & XVID_GLOBAL_DIVX5_USERDATA)) {
BitstreamWriteUserData(bs, DIVX5_ID, strlen(DIVX5_ID));
if (pParam->max_bframes > 0 && (pParam->global_flags & XVID_GLOBAL_PACKED))
BitstreamPutBits(bs, 'p', 8);
}
/* xvid id */
{
const char xvid_user_format[] = "XviD%04d%c";
char xvid_user_data[100];
sprintf(xvid_user_data,
xvid_user_format,
XVID_BS_VERSION,
(frame->vop_flags & XVID_VOP_CARTOON)?'C':'\0');
BitstreamWriteUserData(bs, xvid_user_data, strlen(xvid_user_data));
}
}
/*
write vop header
*/
void
BitstreamWriteVopHeader(
Bitstream * const bs,
const MBParam * pParam,
const FRAMEINFO * const frame,
int vop_coded,
unsigned int quant)
{
uint32_t i;
#if 0
BitstreamPad(bs);
#endif
/*
* no padding here, anymore. You have to make sure that you are
* byte aligned, and that always 1-8 padding bits have been written
*/
BitstreamPutBits(bs, VOP_START_CODE, 32);
BitstreamPutBits(bs, frame->coding_type, 2);
#if 0
DPRINTF(XVID_DEBUG_HEADER, "coding_type = %i\n", frame->coding_type);
#endif
for (i = 0; i < frame->seconds; i++) {
BitstreamPutBit(bs, 1);
}
BitstreamPutBit(bs, 0);
WRITE_MARKER();
/* time_increment: value=nth_of_sec, nbits = log2(resolution) */
BitstreamPutBits(bs, frame->ticks, MAX(log2bin(pParam->fbase-1), 1));
#if 0
DPRINTF("[%i:%i] %c",
frame->seconds, frame->ticks,
frame->coding_type == I_VOP ? 'I' :
frame->coding_type == P_VOP ? 'P' :
frame->coding_type == S_VOP ? 'S' : 'B');
#endif
WRITE_MARKER();
if (!vop_coded) {
BitstreamPutBits(bs, 0, 1);
#if 0
BitstreamPadAlways(bs); /* next_start_code() */
#endif
/* NB: It's up to the function caller to write the next_start_code().
* At the moment encoder.c respects that requisite because a VOP
* always ends with a next_start_code either if it's coded or not
* and encoder.c terminates a frame with a next_start_code in whatever
* case */
return;
}
BitstreamPutBits(bs, 1, 1); /* vop_coded */
if ( (frame->coding_type == P_VOP) || (frame->coding_type == S_VOP) )
BitstreamPutBits(bs, frame->rounding_type, 1);
BitstreamPutBits(bs, 0, 3); /* intra_dc_vlc_threshold */
if ((frame->vol_flags & XVID_VOL_INTERLACING)) {
BitstreamPutBit(bs, (frame->vop_flags & XVID_VOP_TOPFIELDFIRST));
BitstreamPutBit(bs, (frame->vop_flags & XVID_VOP_ALTERNATESCAN));
}
if (frame->coding_type == S_VOP) {
if (1) { /* no_of_sprite_warping_points>=1 (we use 2!) */
int k;
for (k=0;k<3;k++)
{
bs_put_spritetrajectory(bs, frame->warp.duv[k].x ); /* du[k] */
WRITE_MARKER();
bs_put_spritetrajectory(bs, frame->warp.duv[k].y ); /* dv[k] */
WRITE_MARKER();
if ((frame->vol_flags & XVID_VOL_QUARTERPEL))
{
DPRINTF(XVID_DEBUG_HEADER,"sprite_warping_point[%i] xy=(%i,%i) *QPEL*\n", k, frame->warp.duv[k].x/2, frame->warp.duv[k].y/2);
}
else
{
DPRINTF(XVID_DEBUG_HEADER,"sprite_warping_point[%i] xy=(%i,%i)\n", k, frame->warp.duv[k].x, frame->warp.duv[k].y);
}
}
}
}
#if 0
DPRINTF(XVID_DEBUG_HEADER, "quant = %i\n", quant);
#endif
BitstreamPutBits(bs, quant, 5); /* quantizer */
if (frame->coding_type != I_VOP)
BitstreamPutBits(bs, frame->fcode, 3); /* forward_fixed_code */
if (frame->coding_type == B_VOP)
BitstreamPutBits(bs, frame->bcode, 3); /* backward_fixed_code */
}
void
BitstreamWriteUserData(Bitstream * const bs,
const char *data,
const unsigned int length)
{
int i;
BitstreamPad(bs);
BitstreamPutBits(bs, USERDATA_START_CODE, 32);
for (i = 0; i < length; i++) {
BitstreamPutBits(bs, data[i], 8);
}
}
/*
* Group of VOP
*/
void
BitstreamWriteGroupOfVopHeader(Bitstream * const bs,
const MBParam * pParam,
uint32_t is_closed_gov)
{
int64_t time = (pParam->m_stamp + (pParam->fbase/2)) / pParam->fbase;
int hours, minutes, seconds;
/* compute time_code */
seconds = time % 60; time /= 60;
minutes = time % 60; time /= 60;
hours = time % 24; /* don't overflow */
BitstreamPutBits(bs, GRPOFVOP_START_CODE, 32);
BitstreamPutBits(bs, hours, 5);
BitstreamPutBits(bs, minutes, 6);
BitstreamPutBit(bs, 1);
BitstreamPutBits(bs, seconds, 6);
BitstreamPutBits(bs, is_closed_gov, 1);
BitstreamPutBits(bs, 0, 1); /* broken_link */
}
/*
* End of Sequence
*/
void
BitstreamWriteEndOfSequence(Bitstream * const bs)
{
BitstreamPadAlways(bs);
BitstreamPutBits(bs, VISOBJSEQ_STOP_CODE, 32);
}
/*
* Video Packet (resync marker)
*/
void write_video_packet_header(Bitstream * const bs,
const MBParam * pParam,
const FRAMEINFO * const frame,
int mbnum)
{
const int mbnum_bits = log2bin(pParam->mb_width * pParam->mb_height - 1);
uint32_t nbitsresyncmarker;
if (frame->coding_type == I_VOP)
nbitsresyncmarker = NUMBITS_VP_RESYNC_MARKER; /* 16 zeros followed by a 1. */
else if (frame->coding_type == P_VOP)
nbitsresyncmarker = NUMBITS_VP_RESYNC_MARKER-1 + frame->fcode;
else /* B_VOP */
nbitsresyncmarker = MAX(NUMBITS_VP_RESYNC_MARKER+1, NUMBITS_VP_RESYNC_MARKER-1 + MAX(frame->fcode, frame->bcode));
BitstreamPadAlways(bs);
BitstreamPutBits(bs, RESYNC_MARKER, nbitsresyncmarker);
BitstreamPutBits(bs, mbnum, mbnum_bits);
BitstreamPutBits(bs, frame->quant, 5);
BitstreamPutBit(bs, 0); /* hec */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -