Commit 6dbd39fe authored by Juanjo's avatar Juanjo

Added support to Unrestricted Motion Vectors (UMV)

on H.263+ encoding/decoding. According to Annex D.
Now MV on H.263+ are 32x32 long.


Originally committed as revision 113 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 6bbc662f
/* /*
* H263/MPEG4 backend for ffmpeg encoder and decoder * H263/MPEG4 backend for ffmpeg encoder and decoder
* Copyright (c) 2000,2001 Gerard Lantau. * Copyright (c) 2000,2001 Gerard Lantau.
* H263+ support for custom picture format. * H263+ support.
* Copyright (c) 2001 Juan J. Sierralta P. * Copyright (c) 2001 Juan J. Sierralta P.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -28,14 +28,21 @@ ...@@ -28,14 +28,21 @@
static void h263_encode_block(MpegEncContext * s, DCTELEM * block, static void h263_encode_block(MpegEncContext * s, DCTELEM * block,
int n); int n);
static void h263_encode_motion(MpegEncContext * s, int val); 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, static void mpeg4_encode_block(MpegEncContext * s, DCTELEM * block,
int n); int n);
static int h263_decode_motion(MpegEncContext * s, int pred); 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, static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded); int n, int coded);
static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, static int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded); 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 h263_get_picture_format(int width, int height)
{ {
int format; int format;
...@@ -57,7 +64,7 @@ int h263_get_picture_format(int width, int height) ...@@ -57,7 +64,7 @@ int h263_get_picture_format(int width, int height)
void h263_encode_picture_header(MpegEncContext * s, int picture_number) void h263_encode_picture_header(MpegEncContext * s, int picture_number)
{ {
int format, umvplus; int format;
align_put_bits(&s->pb); align_put_bits(&s->pb);
put_bits(&s->pb, 22, 0x20); put_bits(&s->pb, 22, 0x20);
...@@ -70,9 +77,9 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) ...@@ -70,9 +77,9 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
put_bits(&s->pb, 1, 0); /* camera off */ put_bits(&s->pb, 1, 0); /* camera off */
put_bits(&s->pb, 1, 0); /* freeze picture release off */ put_bits(&s->pb, 1, 0); /* freeze picture release off */
format = h263_get_picture_format(s->width, s->height);
if (!s->h263_plus) { if (!s->h263_plus) {
/* H.263v1 */ /* H.263v1 */
format = h263_get_picture_format(s->width, s->height);
put_bits(&s->pb, 3, format); put_bits(&s->pb, 3, format);
put_bits(&s->pb, 1, (s->pict_type == P_TYPE)); put_bits(&s->pb, 1, (s->pict_type == P_TYPE));
/* By now UMV IS DISABLED ON H.263v1, since the restrictions /* By now UMV IS DISABLED ON H.263v1, since the restrictions
...@@ -89,7 +96,11 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) ...@@ -89,7 +96,11 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
/* H.263 Plus PTYPE */ /* H.263 Plus PTYPE */
put_bits(&s->pb, 3, 7); put_bits(&s->pb, 3, 7);
put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */ put_bits(&s->pb,3,1); /* Update Full Extended PTYPE */
if (format == 7)
put_bits(&s->pb,3,6); /* Custom Source Format */ 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 */ put_bits(&s->pb,1,0); /* Custom PCF: off */
umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv; umvplus = (s->pict_type == P_TYPE) && s->unrestricted_mv;
put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */ put_bits(&s->pb, 1, umvplus); /* Unrestricted Motion Vector */
...@@ -116,12 +127,15 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number) ...@@ -116,12 +127,15 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
/* This should be here if PLUSPTYPE */ /* This should be here if PLUSPTYPE */
put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */ put_bits(&s->pb, 1, 0); /* Continuous Presence Multipoint mode: off */
if (format == 7) {
/* Custom Picture Format (CPFMT) */ /* Custom Picture Format (CPFMT) */
put_bits(&s->pb,4,2); /* Aspect ratio: CIF 12:11 (4:3) picture */ 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,9,(s->width >> 2) - 1);
put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */
put_bits(&s->pb,9,(s->height >> 2)); put_bits(&s->pb,9,(s->height >> 2));
}
/* Unlimited Unrestricted Motion Vectors Indicator (UUI) */ /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
if (umvplus) if (umvplus)
put_bits(&s->pb,1,1); /* Limited according tables of Annex D */ put_bits(&s->pb,1,1); /* Limited according tables of Annex D */
...@@ -162,8 +176,17 @@ void h263_encode_mb(MpegEncContext * s, ...@@ -162,8 +176,17 @@ void h263_encode_mb(MpegEncContext * s,
/* motion vectors: 16x16 mode only now */ /* motion vectors: 16x16 mode only now */
h263_pred_motion(s, 0, &pred_x, &pred_y); h263_pred_motion(s, 0, &pred_x, &pred_y);
if (!umvplus) {
h263_encode_motion(s, motion_x - pred_x); h263_encode_motion(s, motion_x - pred_x);
h263_encode_motion(s, motion_y - pred_y); 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 { } else {
/* compute cbp */ /* compute cbp */
cbp = 0; cbp = 0;
...@@ -305,6 +328,45 @@ static void h263_encode_motion(MpegEncContext * s, int val) ...@@ -305,6 +328,45 @@ static void h263_encode_motion(MpegEncContext * s, int val)
} }
} }
/* 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) void h263_encode_init_vlc(MpegEncContext *s)
{ {
static int done = 0; static int done = 0;
...@@ -763,26 +825,45 @@ int h263_decode_mb(MpegEncContext *s, ...@@ -763,26 +825,45 @@ int h263_decode_mb(MpegEncContext *s,
/* 16x16 motion prediction */ /* 16x16 motion prediction */
s->mv_type = MV_TYPE_16X16; s->mv_type = MV_TYPE_16X16;
h263_pred_motion(s, 0, &pred_x, &pred_y); h263_pred_motion(s, 0, &pred_x, &pred_y);
if (umvplus_dec)
mx = h263p_decode_umotion(s, pred_x);
else
mx = h263_decode_motion(s, pred_x); mx = h263_decode_motion(s, pred_x);
if (mx >= 0xffff) if (mx >= 0xffff)
return -1; return -1;
if (umvplus_dec)
my = h263p_decode_umotion(s, pred_y);
else
my = h263_decode_motion(s, pred_y); my = h263_decode_motion(s, pred_y);
if (my >= 0xffff) if (my >= 0xffff)
return -1; return -1;
s->mv[0][0][0] = mx; s->mv[0][0][0] = mx;
s->mv[0][0][1] = my; 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 { } else {
s->mv_type = MV_TYPE_8X8; s->mv_type = MV_TYPE_8X8;
for(i=0;i<4;i++) { for(i=0;i<4;i++) {
mot_val = h263_pred_motion(s, i, &pred_x, &pred_y); mot_val = h263_pred_motion(s, i, &pred_x, &pred_y);
if (umvplus_dec)
mx = h263p_decode_umotion(s, pred_x);
else
mx = h263_decode_motion(s, pred_x); mx = h263_decode_motion(s, pred_x);
if (mx >= 0xffff) if (mx >= 0xffff)
return -1; return -1;
if (umvplus_dec)
my = h263p_decode_umotion(s, pred_y);
else
my = h263_decode_motion(s, pred_y); my = h263_decode_motion(s, pred_y);
if (my >= 0xffff) if (my >= 0xffff)
return -1; return -1;
s->mv[0][i][0] = mx; s->mv[0][i][0] = mx;
s->mv[0][i][1] = my; 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[0] = mx;
mot_val[1] = my; mot_val[1] = my;
} }
...@@ -857,6 +938,32 @@ static int h263_decode_motion(MpegEncContext * s, int pred) ...@@ -857,6 +938,32 @@ static int h263_decode_motion(MpegEncContext * s, int pred)
return val; 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, static int h263_decode_block(MpegEncContext * s, DCTELEM * block,
int n, int coded) int n, int coded)
{ {
...@@ -1108,23 +1215,47 @@ int h263_decode_picture_header(MpegEncContext *s) ...@@ -1108,23 +1215,47 @@ int h263_decode_picture_header(MpegEncContext *s)
} else { } else {
s->h263_plus = 1; s->h263_plus = 1;
/* H.263v2 */ /* H.263v2 */
if (get_bits(&s->gb, 3) != 1) /* OPPTYPE */
return -1;
if (get_bits(&s->gb, 3) != 6) /* custom source format */ if (get_bits(&s->gb, 3) != 1) /* Update Full Extended PTYPE */
return -1; return -1;
skip_bits(&s->gb, 12); format = get_bits(&s->gb, 3);
skip_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; s->pict_type = get_bits(&s->gb, 3) + 1;
if (s->pict_type != I_TYPE && if (s->pict_type != I_TYPE &&
s->pict_type != P_TYPE) s->pict_type != P_TYPE)
return -1; return -1;
skip_bits(&s->gb, 7); skip_bits(&s->gb, 7);
/* Get the picture dimensions */
if (format == 6) {
/* Custom Picture Format (CPFMT) */
skip_bits(&s->gb, 4); /* aspect ratio */ skip_bits(&s->gb, 4); /* aspect ratio */
width = (get_bits(&s->gb, 9) + 1) * 4; width = (get_bits(&s->gb, 9) + 1) * 4;
skip_bits1(&s->gb); skip_bits1(&s->gb);
height = get_bits(&s->gb, 9) * 4; height = get_bits(&s->gb, 9) * 4;
if (height == 0) #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; return -1;
if (umvplus_dec) {
skip_bits1(&s->gb); /* Unlimited Unrestricted Motion Vectors Indicator (UUI) */
}
s->qscale = get_bits(&s->gb, 5); s->qscale = get_bits(&s->gb, 5);
} }
/* PEI */ /* PEI */
......
...@@ -277,7 +277,7 @@ int MPV_encode_init(AVCodecContext *avctx) ...@@ -277,7 +277,7 @@ int MPV_encode_init(AVCodecContext *avctx)
case CODEC_ID_H263P: case CODEC_ID_H263P:
s->out_format = FMT_H263; s->out_format = FMT_H263;
s->h263_plus = 1; s->h263_plus = 1;
/* XXX: not unrectricted mv yet */ s->unrestricted_mv = 1;
break; break;
case CODEC_ID_RV10: case CODEC_ID_RV10:
s->out_format = FMT_H263; s->out_format = FMT_H263;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment