📄 bitstream.c
字号:
} 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 voidbs_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*/voidBitstreamWriteVolHeader(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*/voidBitstreamWriteVopHeader( 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 */}voidBitstreamWriteUserData(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 */voidBitstreamWriteGroupOfVopHeader(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 */voidBitstreamWriteEndOfSequence(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, 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 + -