@ -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 @@ int h263_get_picture_format(int width, int height)
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 @@ 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 ) ; /* 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 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
/* 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 @@ void h263_encode_picture_header(MpegEncContext * s, int picture_number)
/* 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 @@ void h263_encode_mb(MpegEncContext * s,
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 ] ) ;
/* 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 {
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 ) ;
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 @@ 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 )
{
static int done = 0 ;
@ -763,26 +825,45 @@ int h263_decode_mb(MpegEncContext *s,
/* 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 @@ static int h263_decode_motion(MpegEncContext * s, int pred)
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 @@ int h263_decode_picture_header(MpegEncContext *s)
} else {
s - > h263_plus = 1 ;
/* H.263v2 */
if ( get_bits ( & s - > gb , 3 ) ! = 1 )
return - 1 ;
if ( get_bits ( & s - > gb , 3 ) ! = 6 ) /* custom source format */
/* OPPTYPE */
if ( get_bits ( & s - > gb , 3 ) ! = 1 ) /* Update Full Extended PTYPE */
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 , " \n H.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 */