📄 msmpeg4.c
字号:
if(start_code!=0x00000100){
av_log(s->avctx, AV_LOG_ERROR, "invalid startcode\n");
return -1;
}
num= get_bits(&s->gb, 5); // frame number */
}
s->pict_type = get_bits(&s->gb, 2) + 1;
if (s->pict_type != I_TYPE &&
s->pict_type != P_TYPE){
av_log(s->avctx, AV_LOG_ERROR, "invalid picture type\n");
return -1;
}
#if 0
{
static int had_i=0;
if(s->pict_type == I_TYPE) had_i=1;
if(!had_i) return -1;
}
#endif
s->chroma_qscale= s->qscale = get_bits(&s->gb, 5);
if(s->qscale==0){
av_log(s->avctx, AV_LOG_ERROR, "invalid qscale\n");
return -1;
}
if (s->pict_type == I_TYPE) {
code = get_bits(&s->gb, 5);
if(s->msmpeg4_version==1){
if(code==0 || code>s->mb_height){
av_log(s->avctx, AV_LOG_ERROR, "invalid slice height %d\n", code);
return -1;
}
s->slice_height = code;
}else{
/* 0x17: one slice, 0x18: two slices, ... */
if (code < 0x17){
av_log(s->avctx, AV_LOG_ERROR, "error, slice code was %X\n", code);
return -1;
}
s->slice_height = s->mb_height / (code - 0x16);
}
switch(s->msmpeg4_version){
case 1:
case 2:
s->rl_chroma_table_index = 2;
s->rl_table_index = 2;
s->dc_table_index = 0; //not used
break;
case 3:
s->rl_chroma_table_index = decode012(&s->gb);
s->rl_table_index = decode012(&s->gb);
s->dc_table_index = get_bits1(&s->gb);
break;
case 4:
msmpeg4_decode_ext_header(s, (2+5+5+17+7)/8);
if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb);
else s->per_mb_rl_table= 0;
if(!s->per_mb_rl_table){
s->rl_chroma_table_index = decode012(&s->gb);
s->rl_table_index = decode012(&s->gb);
}
s->dc_table_index = get_bits1(&s->gb);
s->inter_intra_pred= 0;
break;
}
s->no_rounding = 1;
if(s->avctx->debug&FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d slice:%d \n",
s->qscale,
s->rl_chroma_table_index,
s->rl_table_index,
s->dc_table_index,
s->per_mb_rl_table,
s->slice_height);
} else {
switch(s->msmpeg4_version){
case 1:
case 2:
if(s->msmpeg4_version==1)
s->use_skip_mb_code = 1;
else
s->use_skip_mb_code = get_bits1(&s->gb);
s->rl_table_index = 2;
s->rl_chroma_table_index = s->rl_table_index;
s->dc_table_index = 0; //not used
s->mv_table_index = 0;
break;
case 3:
s->use_skip_mb_code = get_bits1(&s->gb);
s->rl_table_index = decode012(&s->gb);
s->rl_chroma_table_index = s->rl_table_index;
s->dc_table_index = get_bits1(&s->gb);
s->mv_table_index = get_bits1(&s->gb);
break;
case 4:
s->use_skip_mb_code = get_bits1(&s->gb);
if(s->bit_rate > MBAC_BITRATE) s->per_mb_rl_table= get_bits1(&s->gb);
else s->per_mb_rl_table= 0;
if(!s->per_mb_rl_table){
s->rl_table_index = decode012(&s->gb);
s->rl_chroma_table_index = s->rl_table_index;
}
s->dc_table_index = get_bits1(&s->gb);
s->mv_table_index = get_bits1(&s->gb);
s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE);
break;
}
if(s->avctx->debug&FF_DEBUG_PICT_INFO)
av_log(s->avctx, AV_LOG_DEBUG, "skip:%d rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d \n",
s->use_skip_mb_code,
s->rl_table_index,
s->rl_chroma_table_index,
s->dc_table_index,
s->mv_table_index,
s->per_mb_rl_table,
s->qscale);
if(s->flipflop_rounding){
s->no_rounding ^= 1;
}else{
s->no_rounding = 0;
}
}
//printf("%d %d %d %d %d\n", s->pict_type, s->bit_rate, s->inter_intra_pred, s->width, s->height);
s->esc3_level_length= 0;
s->esc3_run_length= 0;
#ifdef DEBUG
av_log(s->avctx, AV_LOG_DEBUG, "*****frame %d:\n", frame_count++);
#endif
return 0;
}
int msmpeg4_decode_ext_header(MpegEncContext * s, int buf_size)
{
int left= buf_size*8 - get_bits_count(&s->gb);
int length= s->msmpeg4_version>=3 ? 17 : 16;
/* the alt_bitstream reader could read over the end so we need to check it */
if(left>=length && left<length+8)
{
int fps;
fps= get_bits(&s->gb, 5);
s->bit_rate= get_bits(&s->gb, 11)*1024;
if(s->msmpeg4_version>=3)
s->flipflop_rounding= get_bits1(&s->gb);
else
s->flipflop_rounding= 0;
// printf("fps:%2d bps:%2d roundingType:%1d\n", fps, s->bit_rate/1024, s->flipflop_rounding);
}
else if(left<length+8)
{
s->flipflop_rounding= 0;
if(s->msmpeg4_version != 2)
av_log(s->avctx, AV_LOG_ERROR, "ext header missing, %d left\n", left);
}
else
{
av_log(s->avctx, AV_LOG_ERROR, "I frame too long, ignoring ext header\n");
}
return 0;
}
static inline void msmpeg4_memsetw(short *tab, int val, int n)
{
int i;
for(i=0;i<n;i++)
tab[i] = val;
}
#ifdef CONFIG_ENCODERS
static void msmpeg4v2_encode_motion(MpegEncContext * s, int val)
{
int range, bit_size, sign, code, bits;
if (val == 0) {
/* zero vector */
code = 0;
put_bits(&s->pb, mvtab[code][1], mvtab[code][0]);
} else {
bit_size = s->f_code - 1;
range = 1 << bit_size;
if (val <= -64)
val += 64;
else if (val >= 64)
val -= 64;
if (val >= 0) {
sign = 0;
} else {
val = -val;
sign = 1;
}
val--;
code = (val >> bit_size) + 1;
bits = val & (range - 1);
put_bits(&s->pb, mvtab[code][1] + 1, (mvtab[code][0] << 1) | sign);
if (bit_size > 0) {
put_bits(&s->pb, bit_size, bits);
}
}
}
#endif
/* This is identical to h263 except that its range is multiplied by 2. */
static int msmpeg4v2_decode_motion(MpegEncContext * s, int pred, int f_code)
{
int code, val, sign, shift;
code = get_vlc2(&s->gb, v2_mv_vlc.table, V2_MV_VLC_BITS, 2);
// printf("MV code %d at %d %d pred: %d\n", code, s->mb_x,s->mb_y, pred);
if (code < 0)
return 0xffff;
if (code == 0)
return pred;
sign = get_bits1(&s->gb);
shift = f_code - 1;
val = code;
if (shift) {
val = (val - 1) << shift;
val |= get_bits(&s->gb, shift);
val++;
}
if (sign)
val = -val;
val += pred;
if (val <= -64)
val += 64;
else if (val >= 64)
val -= 64;
return val;
}
static int msmpeg4v12_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
{
int cbp, code, i;
if (s->pict_type == P_TYPE) {
if (s->use_skip_mb_code) {
if (get_bits1(&s->gb)) {
/* skip mb */
s->mb_intra = 0;
for(i=0;i<6;i++)
s->block_last_index[i] = -1;
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
s->mv[0][0][0] = 0;
s->mv[0][0][1] = 0;
s->mb_skipped = 1;
return 0;
}
}
if(s->msmpeg4_version==2)
code = get_vlc2(&s->gb, v2_mb_type_vlc.table, V2_MB_TYPE_VLC_BITS, 1);
else
code = get_vlc2(&s->gb, v1_inter_cbpc_vlc.table, V1_INTER_CBPC_VLC_BITS, 3);
if(code<0 || code>7){
av_log(s->avctx, AV_LOG_ERROR, "cbpc %d invalid at %d %d\n", code, s->mb_x, s->mb_y);
return -1;
}
s->mb_intra = code >>2;
cbp = code & 0x3;
} else {
s->mb_intra = 1;
if(s->msmpeg4_version==2)
cbp= get_vlc2(&s->gb, v2_intra_cbpc_vlc.table, V2_INTRA_CBPC_VLC_BITS, 1);
else
cbp= get_vlc2(&s->gb, v1_intra_cbpc_vlc.table, V1_INTRA_CBPC_VLC_BITS, 1);
if(cbp<0 || cbp>3){
av_log(s->avctx, AV_LOG_ERROR, "cbpc %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);
return -1;
}
}
if (!s->mb_intra) {
int mx, my, cbpy;
cbpy= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1);
if(cbpy<0){
av_log(s->avctx, AV_LOG_ERROR, "cbpy %d invalid at %d %d\n", cbp, s->mb_x, s->mb_y);
return -1;
}
cbp|= cbpy<<2;
if(s->msmpeg4_version==1 || (cbp&3) != 3) cbp^= 0x3C;
h263_pred_motion(s, 0, 0, &mx, &my);
mx= msmpeg4v2_decode_motion(s, mx, 1);
my= msmpeg4v2_decode_motion(s, my, 1);
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
s->mv[0][0][0] = mx;
s->mv[0][0][1] = my;
} else {
if(s->msmpeg4_version==2){
s->ac_pred = get_bits1(&s->gb);
cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
} else{
s->ac_pred = 0;
cbp|= get_vlc2(&s->gb, cbpy_vlc.table, CBPY_VLC_BITS, 1)<<2; //FIXME check errors
if(s->pict_type==P_TYPE) cbp^=0x3C;
}
}
s->dsp.clear_blocks(s->block[0]);
for (i = 0; i < 6; i++) {
if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0)
{
av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding block: %d x %d (%d)\n", s->mb_x, s->mb_y, i);
return -1;
}
}
return 0;
}
static int msmpeg4v34_decode_mb(MpegEncContext *s, DCTELEM block[6][64])
{
int cbp, code, i;
uint8_t *coded_val;
uint32_t * const mb_type_ptr= &s->current_picture.mb_type[ s->mb_x + s->mb_y*s->mb_stride ];
if (s->pict_type == P_TYPE) {
if (s->use_skip_mb_code) {
if (get_bits1(&s->gb)) {
/* skip mb */
s->mb_intra = 0;
for(i=0;i<6;i++)
s->block_last_index[i] = -1;
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
s->mv[0][0][0] = 0;
s->mv[0][0][1] = 0;
s->mb_skipped = 1;
*mb_type_ptr = MB_TYPE_SKIP | MB_TYPE_L0 | MB_TYPE_16x16;
return 0;
}
}
code = get_vlc2(&s->gb, mb_non_intra_vlc[DEFAULT_INTER_INDEX].table, MB_NON_INTRA_VLC_BITS, 3);
if (code < 0)
return -1;
//s->mb_intra = (code & 0x40) ? 0 : 1;
s->mb_intra = (~code & 0x40) >> 6;
cbp = code & 0x3f;
} else {
s->mb_intra = 1;
code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2);
if (code < 0)
return -1;
/* predict coded block pattern */
cbp = 0;
for(i=0;i<6;i++) {
int val = ((code >> (5 - i)) & 1);
if (i < 4) {
int pred = coded_block_pred(s, i, &coded_val);
val = val ^ pred;
*coded_val = val;
}
cbp |= val << (5 - i);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -