mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
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
This commit is contained in:
parent
6bbc662f7d
commit
6dbd39fe70
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* 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 @@
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
||||||
@ -69,10 +76,10 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
|
|||||||
put_bits(&s->pb, 1, 0); /* split screen off */
|
put_bits(&s->pb, 1, 0); /* split screen off */
|
||||||
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)
|
|||||||
/* 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 */
|
||||||
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 */
|
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)
|
|||||||
/* 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 */
|
||||||
|
|
||||||
/* 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,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 */
|
||||||
@ -138,33 +152,42 @@ void h263_encode_mb(MpegEncContext * s,
|
|||||||
int cbpc, cbpy, i, cbp, pred_x, pred_y;
|
int cbpc, cbpy, i, cbp, pred_x, pred_y;
|
||||||
|
|
||||||
// printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
|
// printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
|
||||||
if (!s->mb_intra) {
|
if (!s->mb_intra) {
|
||||||
/* compute cbp */
|
/* compute cbp */
|
||||||
cbp = 0;
|
cbp = 0;
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
if (s->block_last_index[i] >= 0)
|
if (s->block_last_index[i] >= 0)
|
||||||
cbp |= 1 << (5 - i);
|
cbp |= 1 << (5 - i);
|
||||||
}
|
}
|
||||||
if ((cbp | motion_x | motion_y) == 0) {
|
if ((cbp | motion_x | motion_y) == 0) {
|
||||||
/* skip macroblock */
|
/* skip macroblock */
|
||||||
put_bits(&s->pb, 1, 1);
|
put_bits(&s->pb, 1, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
put_bits(&s->pb, 1, 0); /* mb coded */
|
put_bits(&s->pb, 1, 0); /* mb coded */
|
||||||
cbpc = cbp & 3;
|
cbpc = cbp & 3;
|
||||||
put_bits(&s->pb,
|
put_bits(&s->pb,
|
||||||
inter_MCBPC_bits[cbpc],
|
inter_MCBPC_bits[cbpc],
|
||||||
inter_MCBPC_code[cbpc]);
|
inter_MCBPC_code[cbpc]);
|
||||||
cbpy = cbp >> 2;
|
cbpy = cbp >> 2;
|
||||||
cbpy ^= 0xf;
|
cbpy ^= 0xf;
|
||||||
put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
|
put_bits(&s->pb, cbpy_tab[cbpy][1], cbpy_tab[cbpy][0]);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
h263_encode_motion(s, motion_x - pred_x);
|
if (!umvplus) {
|
||||||
h263_encode_motion(s, motion_y - pred_y);
|
h263_encode_motion(s, motion_x - pred_x);
|
||||||
} else {
|
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 */
|
/* compute cbp */
|
||||||
cbp = 0;
|
cbp = 0;
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
@ -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,
|
|||||||
/* 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);
|
||||||
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)
|
if (mx >= 0xffff)
|
||||||
return -1;
|
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)
|
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);
|
||||||
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)
|
if (mx >= 0xffff)
|
||||||
return -1;
|
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)
|
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)
|
|||||||
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)
|
|||||||
} else {
|
} else {
|
||||||
s->h263_plus = 1;
|
s->h263_plus = 1;
|
||||||
/* H.263v2 */
|
/* H.263v2 */
|
||||||
if (get_bits(&s->gb, 3) != 1)
|
/* OPPTYPE */
|
||||||
|
|
||||||
|
if (get_bits(&s->gb, 3) != 1) /* Update Full Extended PTYPE */
|
||||||
return -1;
|
return -1;
|
||||||
if (get_bits(&s->gb, 3) != 6) /* custom source format */
|
format = get_bits(&s->gb, 3);
|
||||||
return -1;
|
|
||||||
skip_bits(&s->gb, 12);
|
skip_bits(&s->gb,1); /* Custom PCF */
|
||||||
skip_bits(&s->gb, 3);
|
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);
|
||||||
skip_bits(&s->gb, 4); /* aspect ratio */
|
|
||||||
width = (get_bits(&s->gb, 9) + 1) * 4;
|
/* Get the picture dimensions */
|
||||||
skip_bits1(&s->gb);
|
if (format == 6) {
|
||||||
height = get_bits(&s->gb, 9) * 4;
|
/* Custom Picture Format (CPFMT) */
|
||||||
if (height == 0)
|
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;
|
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)
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user