# HG changeset patch # User pulento # Date 999041554 0 # Node ID 92ed1c4f94fade65690a2d8ef31f12c10b7bc546 # Parent 9e8ae8222ddc888b87930d278d43a45874808afa Added support to Unrestricted Motion Vectors (UMV) on H.263+ encoding/decoding. According to Annex D. Now MV on H.263+ are 32x32 long. diff -r 9e8ae8222ddc -r 92ed1c4f94fa h263.c --- a/h263.c Mon Aug 20 16:01:35 2001 +0000 +++ b/h263.c Tue Aug 28 23:32:34 2001 +0000 @@ -1,7 +1,7 @@ /* * H263/MPEG4 backend for ffmpeg encoder and decoder * Copyright (c) 2000,2001 Gerard Lantau. - * H263+ support for custom picture format. + * H263+ support. * Copyright (c) 2001 Juan J. Sierralta P. * * This program is free software; you can redistribute it and/or modify @@ -28,14 +28,21 @@ static void h263_encode_block(MpegEncContext * s, DCTELEM * block, int n); static void h263_encode_motion(MpegEncContext * s, int val); +static void h263p_encode_umotion(MpegEncContext * s, int val); static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block, int n); static int h263_decode_motion(MpegEncContext * s, int pred); +static int h263p_decode_umotion(MpegEncContext * s, int pred); static int h263_decode_block(MpegEncContext * s, DCTELEM * block, int n, int coded); static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, int n, int coded); +/* This are for H.263+ UMV */ +/* Shouldn't be here */ +static int umvplus = 0; +static int umvplus_dec = 0; + int h263_get_picture_format(int width, int height) { int format; @@ -57,7 +64,7 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) { - int format, umvplus; + int format; align_put_bits(&s->pb); put_bits(&s->pb, 22, 0x20); @@ -69,10 +76,10 @@ put_bits(&s->pb, 1, 0); /* split screen off */ put_bits(&s->pb, 1, 0); /* camera off */ put_bits(&s->pb, 1, 0); /* freeze picture release off */ - + + format = h263_get_picture_format(s->width, s->height); if (!s->h263_plus) { /* H.263v1 */ - format = h263_get_picture_format(s->width, s->height); put_bits(&s->pb, 3, format); put_bits(&s->pb, 1, (s->pict_type == P_TYPE)); /* By now UMV IS DISABLED ON H.263v1, since the restrictions @@ -89,7 +96,11 @@ /* H.263 Plus PTYPE */ put_bits(&s->pb, 3, 7); put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */ - put_bits(&s->pb,3,6); /* Custom Source Format */ + if (format == 7) + put_bits(&s->pb,3,6); /* Custom Source Format */ + else + put_bits(&s->pb, 3, format); + put_bits(&s->pb,1,0); /* Custom PCF: off */ umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv; put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */ @@ -116,12 +127,15 @@ /* This should be here if PLUSPTYPE */ put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */ - /* Custom Picture Format (CPFMT) */ + if (format == 7) { + /* Custom Picture Format (CPFMT) */ - put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */ - put_bits(&s->pb,9,(s->width >> 2) - 1); - put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ - put_bits(&s->pb,9,(s->height >> 2)); + put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */ + put_bits(&s->pb,9,(s->width >> 2) - 1); + put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ + put_bits(&s->pb,9,(s->height >> 2)); + } + /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */ if (umvplus) put_bits(&s->pb,1,1); /* Limited according tables of Annex D */ @@ -138,33 +152,42 @@ int cbpc, cbpy, i, cbp, pred_x, pred_y; // printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y); - if (!s->mb_intra) { - /* compute cbp */ - cbp = 0; - for (i = 0; i < 6; i++) { - if (s->block_last_index[i] >= 0) - cbp |= 1 << (5 - i); - } - if ((cbp | motion_x | motion_y) == 0) { - /* skip macroblock */ - put_bits(&s->pb, 1, 1); - return; - } - put_bits(&s->pb, 1, 0); /* mb coded */ - cbpc = cbp & 3; - put_bits(&s->pb, - inter_MCBPC_bits[cbpc], - inter_MCBPC_code[cbpc]); - cbpy = cbp >> 2; - cbpy ^= 0xf; - put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); + if (!s->mb_intra) { + /* compute cbp */ + cbp = 0; + for (i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + if ((cbp | motion_x | motion_y) == 0) { + /* skip macroblock */ + put_bits(&s->pb, 1, 1); + return; + } + put_bits(&s->pb, 1, 0); /* mb coded */ + cbpc = cbp & 3; + put_bits(&s->pb, + inter_MCBPC_bits[cbpc], + inter_MCBPC_code[cbpc]); + cbpy = cbp >> 2; + cbpy ^= 0xf; + put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]); - /* motion vectors: 16x16 mode only now */ - h263_pred_motion(s, 0, &pred_x, &pred_y); - - h263_encode_motion(s, motion_x - pred_x); - h263_encode_motion(s, motion_y - pred_y); - } else { + /* motion vectors: 16x16 mode only now */ + h263_pred_motion(s, 0, &pred_x, &pred_y); + + if (!umvplus) { + h263_encode_motion(s, motion_x - pred_x); + h263_encode_motion(s, motion_y - pred_y); + } + else { + h263p_encode_umotion(s, motion_x - pred_x); + h263p_encode_umotion(s, motion_y - pred_y); + if (((motion_x - pred_x) == 1) && ((motion_y - pred_y) == 1)) + /* To prevent Start Code emulation */ + put_bits(&s->pb,1,1); + } + } else { /* compute cbp */ cbp = 0; for (i = 0; i < 6; i++) { @@ -305,6 +328,45 @@ } } +/* Encode MV differences on H.263+ with Unrestricted MV mode */ +static void h263p_encode_umotion(MpegEncContext * s, int val) +{ + short sval = 0; + short i = 0; + short n_bits = 0; + short temp_val; + int code = 0; + int tcode; + + if ( val == 0) + put_bits(&s->pb, 1, 1); + else if (val == 1) + put_bits(&s->pb, 3, 0); + else if (val == -1) + put_bits(&s->pb, 3, 2); + else { + + sval = ((val < 0) ? (short)(-val):(short)val); + temp_val = sval; + + while (temp_val != 0) { + temp_val = temp_val >> 1; + n_bits++; + } + + i = n_bits - 1; + while (i > 0) { + tcode = (sval & (1 << (i-1))) >> (i-1); + tcode = (tcode << 1) | 1; + code = (code << 2) | tcode; + i--; + } + code = ((code << 1) | (val < 0)) << 1; + put_bits(&s->pb, (2*n_bits)+1, code); + //printf("\nVal = %d\tCode = %d", sval, code); + } +} + void h263_encode_init_vlc(MpegEncContext *s) { static int done = 0; @@ -763,26 +825,45 @@ /* 16x16 motion prediction */ s->mv_type = MV_TYPE_16X16; h263_pred_motion(s, 0, &pred_x, &pred_y); - mx = h263_decode_motion(s, pred_x); + if (umvplus_dec) + mx = h263p_decode_umotion(s, pred_x); + else + mx = h263_decode_motion(s, pred_x); if (mx >= 0xffff) return -1; - my = h263_decode_motion(s, pred_y); + + if (umvplus_dec) + my = h263p_decode_umotion(s, pred_y); + else + my = h263_decode_motion(s, pred_y); if (my >= 0xffff) return -1; s->mv[0][0][0] = mx; s->mv[0][0][1] = my; + if (umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1) + skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */ + } else { s->mv_type = MV_TYPE_8X8; for(i=0;i<4;i++) { mot_val = h263_pred_motion(s, i, &pred_x, &pred_y); - mx = h263_decode_motion(s, pred_x); + if (umvplus_dec) + mx = h263p_decode_umotion(s, pred_x); + else + mx = h263_decode_motion(s, pred_x); if (mx >= 0xffff) return -1; - my = h263_decode_motion(s, pred_y); + + if (umvplus_dec) + my = h263p_decode_umotion(s, pred_y); + else + my = h263_decode_motion(s, pred_y); if (my >= 0xffff) return -1; s->mv[0][i][0] = mx; s->mv[0][i][1] = my; + if (umvplus_dec && (mx - pred_x) == 1 && (my - pred_y) == 1) + skip_bits1(&s->gb); /* Bit stuffing to prevent PSC */ mot_val[0] = mx; mot_val[1] = my; } @@ -857,6 +938,32 @@ return val; } +/* Decodes RVLC of H.263+ UMV */ +static int h263p_decode_umotion(MpegEncContext * s, int pred) +{ + int code = 0, sign; + + if (get_bits1(&s->gb)) /* Motion difference = 0 */ + return pred; + + code = 2 + get_bits1(&s->gb); + + while (get_bits1(&s->gb)) + { + code <<= 1; + code += get_bits1(&s->gb); + } + sign = code & 1; + code >>= 1; + + code = (sign) ? (pred - code) : (pred + code); +#ifdef DEBUG + fprintf(stderr,"H.263+ UMV Motion = %d\n", code); +#endif + return code; + +} + static int h263_decode_block(MpegEncContext * s, DCTELEM * block, int n, int coded) { @@ -1108,23 +1215,47 @@ } else { s->h263_plus = 1; /* H.263v2 */ - if (get_bits(&s->gb, 3) != 1) + /* OPPTYPE */ + + if (get_bits(&s->gb, 3) != 1) /* Update Full Extended PTYPE */ return -1; - if (get_bits(&s->gb, 3) != 6) /* custom source format */ - return -1; - skip_bits(&s->gb, 12); - skip_bits(&s->gb, 3); + format = get_bits(&s->gb, 3); + + skip_bits(&s->gb,1); /* Custom PCF */ + umvplus_dec = get_bits(&s->gb, 1); /* Unrestricted Motion Vector */ + skip_bits(&s->gb, 10); + skip_bits(&s->gb, 3); /* Reserved */ + + /* MPPTYPE */ s->pict_type = get_bits(&s->gb, 3) + 1; if (s->pict_type != I_TYPE && s->pict_type != P_TYPE) return -1; skip_bits(&s->gb, 7); - skip_bits(&s->gb, 4); /* aspect ratio */ - width = (get_bits(&s->gb, 9) + 1) * 4; - skip_bits1(&s->gb); - height = get_bits(&s->gb, 9) * 4; - if (height == 0) + + /* Get the picture dimensions */ + if (format == 6) { + /* Custom Picture Format (CPFMT) */ + skip_bits(&s->gb, 4); /* aspect ratio */ + width = (get_bits(&s->gb, 9) + 1) * 4; + skip_bits1(&s->gb); + height = get_bits(&s->gb, 9) * 4; +#ifdef DEBUG + fprintf(stderr,"\nH.263+ Custom picture: %dx%d\n",width,height); +#endif + } + else { + width = h263_format[format][0]; + height = h263_format[format][1]; + } + + if ((width == 0) || (height == 0)) return -1; + + if (umvplus_dec) { + skip_bits1(&s->gb); /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */ + } + s->qscale = get_bits(&s->gb, 5); } /* PEI */ diff -r 9e8ae8222ddc -r 92ed1c4f94fa mpegvideo.c --- a/mpegvideo.c Mon Aug 20 16:01:35 2001 +0000 +++ b/mpegvideo.c Tue Aug 28 23:32:34 2001 +0000 @@ -277,7 +277,7 @@ case CODEC_ID_H263P: s->out_format = FMT_H263; s->h263_plus = 1; - /* XXX: not unrectricted mv yet */ + s->unrestricted_mv = 1; break; case CODEC_ID_RV10: s->out_format = FMT_H263;