# HG changeset patch # User michaelni # Date 1034798149 0 # Node ID 8e1f0939d15de3eb1c18293d74ceb69bbba2443c # Parent 97077dd24bfa632a533670c87a01bf97b120601c complete mpeg4 GMC decoding support diff -r 97077dd24bfa -r 8e1f0939d15d common.h --- a/common.h Wed Oct 16 17:23:18 2002 +0000 +++ b/common.h Wed Oct 16 19:55:49 2002 +0000 @@ -157,6 +157,8 @@ # define av_abort() do { fprintf(stderr, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0) +//rounded divison & shift +#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) /* assume b>0 */ #define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) #define ABS(a) ((a) >= 0 ? (a) : (-(a))) diff -r 97077dd24bfa -r 8e1f0939d15d dsputil.c --- a/dsputil.c Wed Oct 16 17:23:18 2002 +0000 +++ b/dsputil.c Wed Oct 16 19:55:49 2002 +0000 @@ -25,7 +25,9 @@ void (*diff_pixels)(DCTELEM *block, const UINT8 *s1, const UINT8 *s2, int stride); void (*put_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); void (*add_pixels_clamped)(const DCTELEM *block, UINT8 *pixels, int line_size); -void (*gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); +void (*ff_gmc1)(UINT8 *dst, UINT8 *src, int srcStride, int h, int x16, int y16, int rounder); +void (*ff_gmc )(UINT8 *dst, UINT8 *src, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); void (*clear_blocks)(DCTELEM *blocks); int (*pix_sum)(UINT8 * pix, int line_size); int (*pix_norm1)(UINT8 * pix, int line_size); @@ -822,6 +824,7 @@ #define avg2(a,b) ((a+b+1)>>1) #define avg4(a,b,c,d) ((a+b+c+d+2)>>2) + static void gmc1_c(UINT8 *dst, UINT8 *src, int stride, int h, int x16, int y16, int rounder) { const int A=(16-x16)*(16-y16); @@ -829,7 +832,6 @@ const int C=(16-x16)*( y16); const int D=( x16)*( y16); int i; - rounder= 128 - rounder; for(i=0; i>16; + src_y= vy>>16; + frac_x= src_x&(s-1); + frac_y= src_y&(s-1); + src_x>>=shift; + src_y>>=shift; + + if((unsigned)src_x < width){ + if((unsigned)src_y < height){ + index= src_x + src_y*stride; + dst[y*stride + x]= ( ( src[index ]*(s-frac_x) + + src[index +1]* frac_x )*(s-frac_y) + + ( src[index+stride ]*(s-frac_x) + + src[index+stride+1]* frac_x )* frac_y + + r)>>(shift*2); + }else{ + index= src_x + clip(src_y, 0, height)*stride; + dst[y*stride + x]= ( ( src[index ]*(s-frac_x) + + src[index +1]* frac_x )*s + + r)>>(shift*2); + } + }else{ + if((unsigned)src_y < height){ + index= clip(src_x, 0, width) + src_y*stride; + dst[y*stride + x]= ( ( src[index ]*(s-frac_y) + + src[index+stride ]* frac_y )*s + + r)>>(shift*2); + }else{ + index= clip(src_x, 0, width) + clip(src_y, 0, height)*stride; + dst[y*stride + x]= src[index ]; + } + } + + vx+= dxx; + vy+= dyx; + } + ox += dxy; + oy += dyy; + } +} + static inline void copy_block17(UINT8 *dst, UINT8 *src, int dstStride, int srcStride, int h) { int i; @@ -1528,7 +1588,8 @@ diff_pixels = diff_pixels_c; put_pixels_clamped = put_pixels_clamped_c; add_pixels_clamped = add_pixels_clamped_c; - gmc1= gmc1_c; + ff_gmc1= gmc1_c; + ff_gmc= gmc_c; clear_blocks= clear_blocks_c; pix_sum= pix_sum_c; pix_norm1= pix_norm1_c; diff -r 97077dd24bfa -r 8e1f0939d15d dsputil.h --- a/dsputil.h Wed Oct 16 17:23:18 2002 +0000 +++ b/dsputil.h Wed Oct 16 19:55:49 2002 +0000 @@ -62,7 +62,9 @@ extern void (*diff_pixels)(DCTELEM *block/*align 16*/, const UINT8 *s1/*align 8*/, const UINT8 *s2/*align 8*/, int stride); extern void (*put_pixels_clamped)(const DCTELEM *block/*align 16*/, UINT8 *pixels/*align 8*/, int line_size); extern void (*add_pixels_clamped)(const DCTELEM *block/*align 16*/, UINT8 *pixels/*align 8*/, int line_size); -extern void (*gmc1)(UINT8 *dst/*align 8*/, UINT8 *src/*align 1*/, int srcStride, int h, int x16, int y16, int rounder); +extern void (*ff_gmc1)(UINT8 *dst/*align 8*/, UINT8 *src/*align 1*/, int srcStride, int h, int x16, int y16, int rounder); +extern void (*ff_gmc )(UINT8 *dst/*align 8*/, UINT8 *src/*align 1*/, int stride, int h, int ox, int oy, + int dxx, int dxy, int dyx, int dyy, int shift, int r, int width, int height); extern void (*clear_blocks)(DCTELEM *blocks/*align 16*/); extern int (*pix_sum)(UINT8 * pix, int line_size); extern int (*pix_norm1)(UINT8 * pix, int line_size); diff -r 97077dd24bfa -r 8e1f0939d15d h263.c --- a/h263.c Wed Oct 16 17:23:18 2002 +0000 +++ b/h263.c Wed Oct 16 19:55:49 2002 +0000 @@ -34,9 +34,6 @@ //#undef NDEBUG //#include -//rounded divison & shift -#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b)) - #if 1 #define PRINT_MB_TYPE(a) {} #else @@ -2433,6 +2430,49 @@ } /** + * @param n either 0 for the x component or 1 for y + * @returns the average MV for a GMC MB + */ +static inline int get_amv(MpegEncContext *s, int n){ + int x, y, mb_v, sum, dx, dy, shift; + int len = 1 << (s->f_code + 4); + const int a= s->sprite_warping_accuracy; + + if(s->real_sprite_warping_points==1){ + if(s->divx_version==500 && s->divx_build==413) + sum= s->sprite_offset[0][n] / (1<<(a - s->quarter_sample)); + else + sum= RSHIFT(s->sprite_offset[0][n]<quarter_sample, a); + }else{ + dx= s->sprite_delta[n][0]; + dy= s->sprite_delta[n][1]; + shift= s->sprite_shift[0]; + if(n) dy -= 1<<(shift + a + 1); + else dx -= 1<<(shift + a + 1); + mb_v= s->sprite_offset[0][n] + dx*s->mb_x*16 + dy*s->mb_y*16; + + sum=0; + for(y=0; y<16; y++){ + int v; + + v= mb_v + dy*y; + //XXX FIXME optimize + for(x=0; x<16; x++){ + sum+= v>>shift; + v+= dx; + } + } + sum /= 256; + sum= RSHIFT(sum<quarter_sample, a); + } + + if (sum < -len) sum= -len; + else if (sum >= len) sum= len-1; + + return sum; +} + +/** * decodes first partition. * @return number of MBs decoded or <0 if an error occured */ @@ -2508,20 +2548,12 @@ /* skip mb */ s->mb_type[xy]= MB_TYPE_SKIPED; if(s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE){ - const int a= s->sprite_warping_accuracy; PRINT_MB_TYPE("G"); - if(s->divx_version==500 && s->divx_build==413){ - mx = s->sprite_offset[0][0] / (1<<(a-s->quarter_sample)); - my = s->sprite_offset[0][1] / (1<<(a-s->quarter_sample)); - }else{ - mx = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); - my = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample); - s->mb_type[xy]= MB_TYPE_GMC | MB_TYPE_SKIPED; - } + mx= get_amv(s, 0); + my= get_amv(s, 1); }else{ PRINT_MB_TYPE("S"); - mx = 0; - my = 0; + mx=my=0; } mot_val[0 ]= mot_val[2 ]= mot_val[0+stride]= mot_val[2+stride]= mx; @@ -2570,31 +2602,19 @@ s->mb_type[xy]= MB_TYPE_INTER; h263_pred_motion(s, 0, &pred_x, &pred_y); - if(!s->mcsel) - mx = h263_decode_motion(s, pred_x, s->f_code); - else { - const int a= s->sprite_warping_accuracy; - if(s->divx_version==500 && s->divx_build==413){ - mx = s->sprite_offset[0][0] / (1<<(a-s->quarter_sample)); - }else{ - mx = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); - } + if(!s->mcsel){ + mx = h263_decode_motion(s, pred_x, s->f_code); + if (mx >= 0xffff) + return -1; + + my = h263_decode_motion(s, pred_y, s->f_code); + if (my >= 0xffff) + return -1; + } else { + mx = get_amv(s, 0); + my = get_amv(s, 1); } - if (mx >= 0xffff) - return -1; - - if(!s->mcsel) - my = h263_decode_motion(s, pred_y, s->f_code); - else{ - const int a= s->sprite_warping_accuracy; - if(s->divx_version==500 && s->divx_build==413){ - my = s->sprite_offset[0][1] / (1<<(a-s->quarter_sample)); - }else{ - my = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample); - } - } - if (my >= 0xffff) - return -1; + mot_val[0 ]= mot_val[2 ] = mot_val[0+stride]= mot_val[2+stride]= mx; mot_val[1 ]= mot_val[3 ]= @@ -2876,21 +2896,10 @@ s->mv_dir = MV_DIR_FORWARD; s->mv_type = MV_TYPE_16X16; if(s->pict_type==S_TYPE && s->vol_sprite_usage==GMC_SPRITE){ - const int a= s->sprite_warping_accuracy; -// int l = (1 << (s->f_code - 1)) * 32; PRINT_MB_TYPE("G"); s->mcsel=1; - if(s->divx_version==500 && s->divx_build==413){ - s->mv[0][0][0] = s->sprite_offset[0][0] / (1<<(a-s->quarter_sample)); - s->mv[0][0][1] = s->sprite_offset[0][1] / (1<<(a-s->quarter_sample)); - }else{ - s->mv[0][0][0] = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); - s->mv[0][0][1] = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample); - } -/* if (s->mv[0][0][0] < -l) s->mv[0][0][0]= -l; - else if (s->mv[0][0][0] >= l) s->mv[0][0][0]= l-1; - if (s->mv[0][0][1] < -l) s->mv[0][0][1]= -l; - else if (s->mv[0][0][1] >= l) s->mv[0][0][1]= l-1;*/ + s->mv[0][0][0]= get_amv(s, 0); + s->mv[0][0][1]= get_amv(s, 1); s->mb_skiped = 0; }else{ @@ -2929,19 +2938,11 @@ s->mv_dir = MV_DIR_FORWARD; if ((cbpc & 16) == 0) { if(s->mcsel){ - const int a= s->sprite_warping_accuracy; PRINT_MB_TYPE("G"); /* 16x16 global motion prediction */ s->mv_type = MV_TYPE_16X16; -// int l = (1 << (s->f_code - 1)) * 32; - if(s->divx_version==500 && s->divx_build==413){ - mx = s->sprite_offset[0][0] / (1<<(a-s->quarter_sample)); - my = s->sprite_offset[0][1] / (1<<(a-s->quarter_sample)); - }else{ - mx = RSHIFT(s->sprite_offset[0][0], a-s->quarter_sample); - my = RSHIFT(s->sprite_offset[0][1], a-s->quarter_sample); - } -// int l = (1 << (s->f_code - 1)) * 32; + mx= get_amv(s, 0); + my= get_amv(s, 1); s->mv[0][0][0] = mx; s->mv[0][0][1] = my; }else if((!s->progressive_sequence) && get_bits1(&s->gb)){ @@ -3862,11 +3863,12 @@ int d[4][2]={{0,0}, {0,0}, {0,0}, {0,0}}; int sprite_ref[4][2]; int virtual_ref[2][2]; - int w2, h2; + int w2, h2, w3, h3; int alpha=0, beta=0; int w= s->width; int h= s->height; -//printf("SP %d\n", s->sprite_warping_accuracy); + int min_ab; + for(i=0; inum_sprite_warping_points; i++){ int length; int x=0, y=0; @@ -3874,7 +3876,7 @@ length= get_vlc(&s->gb, &sprite_trajectory); if(length){ x= get_bits(&s->gb, length); -//printf("lx %d %d\n", length, x); + if ((x >> (length - 1)) == 0) /* if MSB not set it is negative*/ x = - (x ^ ((1 << length) - 1)); } @@ -3883,14 +3885,12 @@ length= get_vlc(&s->gb, &sprite_trajectory); if(length){ y=get_bits(&s->gb, length); -//printf("ly %d %d\n", length, y); + if ((y >> (length - 1)) == 0) /* if MSB not set it is negative*/ y = - (y ^ ((1 << length) - 1)); } skip_bits1(&s->gb); /* marker bit */ //printf("%d %d %d %d\n", x, y, i, s->sprite_warping_accuracy); -//if(i>0 && (x!=0 || y!=0)) printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"); -//x=y=0; d[i][0]= x; d[i][1]= y; } @@ -3931,7 +3931,7 @@ + ROUNDED_DIV(((h - h2)*(r*sprite_ref[0][0] - 16*vop_ref[0][0]) + h2*(r*sprite_ref[2][0] - 16*vop_ref[2][0])),h); virtual_ref[1][1]= 16*(vop_ref[0][1] + h2) + ROUNDED_DIV(((h - h2)*(r*sprite_ref[0][1] - 16*vop_ref[0][1]) + h2*(r*sprite_ref[2][1] - 16*vop_ref[2][1])),h); - + switch(s->num_sprite_warping_points) { case 0: @@ -3939,107 +3939,133 @@ s->sprite_offset[0][1]= 0; s->sprite_offset[1][0]= 0; s->sprite_offset[1][1]= 0; - s->sprite_delta[0][0][0]= a; - s->sprite_delta[0][0][1]= 0; - s->sprite_delta[0][1][0]= 0; - s->sprite_delta[0][1][1]= a; - s->sprite_delta[1][0][0]= a; - s->sprite_delta[1][0][1]= 0; - s->sprite_delta[1][1][0]= 0; - s->sprite_delta[1][1][1]= a; - s->sprite_shift[0][0]= 0; - s->sprite_shift[0][1]= 0; - s->sprite_shift[1][0]= 0; - s->sprite_shift[1][1]= 0; + s->sprite_delta[0][0]= a; + s->sprite_delta[0][1]= 0; + s->sprite_delta[1][0]= 0; + s->sprite_delta[1][1]= a; + s->sprite_shift[0]= 0; + s->sprite_shift[1]= 0; break; case 1: //GMC only s->sprite_offset[0][0]= sprite_ref[0][0] - a*vop_ref[0][0]; s->sprite_offset[0][1]= sprite_ref[0][1] - a*vop_ref[0][1]; s->sprite_offset[1][0]= ((sprite_ref[0][0]>>1)|(sprite_ref[0][0]&1)) - a*(vop_ref[0][0]/2); s->sprite_offset[1][1]= ((sprite_ref[0][1]>>1)|(sprite_ref[0][1]&1)) - a*(vop_ref[0][1]/2); - s->sprite_delta[0][0][0]= a; - s->sprite_delta[0][0][1]= 0; - s->sprite_delta[0][1][0]= 0; - s->sprite_delta[0][1][1]= a; - s->sprite_delta[1][0][0]= a; - s->sprite_delta[1][0][1]= 0; - s->sprite_delta[1][1][0]= 0; - s->sprite_delta[1][1][1]= a; - s->sprite_shift[0][0]= 0; - s->sprite_shift[0][1]= 0; - s->sprite_shift[1][0]= 0; - s->sprite_shift[1][1]= 0; + s->sprite_delta[0][0]= a; + s->sprite_delta[0][1]= 0; + s->sprite_delta[1][0]= 0; + s->sprite_delta[1][1]= a; + s->sprite_shift[0]= 0; + s->sprite_shift[1]= 0; break; case 2: - case 3: //FIXME s->sprite_offset[0][0]= (sprite_ref[0][0]<<(alpha+rho)) - + ((-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][0]) - +( r*sprite_ref[0][1] - virtual_ref[0][1])*(-vop_ref[0][1])); + + (-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][0]) + + ( r*sprite_ref[0][1] - virtual_ref[0][1])*(-vop_ref[0][1]) + + (1<<(alpha+rho-1)); s->sprite_offset[0][1]= (sprite_ref[0][1]<<(alpha+rho)) - + ((-r*sprite_ref[0][1] + virtual_ref[0][1])*(-vop_ref[0][0]) - +(-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][1])); - s->sprite_offset[1][0]= ((-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][0] + 1) - +( r*sprite_ref[0][1] - virtual_ref[0][1])*(-2*vop_ref[0][1] + 1) - +2*w2*r*sprite_ref[0][0] - 16*w2); - s->sprite_offset[1][1]= ((-r*sprite_ref[0][1] + virtual_ref[0][1])*(-2*vop_ref[0][0] + 1) - +(-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][1] + 1) - +2*w2*r*sprite_ref[0][1] - 16*w2); - s->sprite_delta[0][0][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); - s->sprite_delta[0][0][1]= ( r*sprite_ref[0][1] - virtual_ref[0][1]); - s->sprite_delta[0][1][0]= (-r*sprite_ref[0][1] + virtual_ref[0][1]); - s->sprite_delta[0][1][1]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); - s->sprite_delta[1][0][0]= 4*(-r*sprite_ref[0][0] + virtual_ref[0][0]); - s->sprite_delta[1][0][1]= 4*( r*sprite_ref[0][1] - virtual_ref[0][1]); - s->sprite_delta[1][1][0]= 4*(-r*sprite_ref[0][1] + virtual_ref[0][1]); - s->sprite_delta[1][1][1]= 4*(-r*sprite_ref[0][0] + virtual_ref[0][0]); - s->sprite_shift[0][0]= alpha+rho; - s->sprite_shift[0][1]= alpha+rho; - s->sprite_shift[1][0]= alpha+rho+2; - s->sprite_shift[1][1]= alpha+rho+2; + + (-r*sprite_ref[0][1] + virtual_ref[0][1])*(-vop_ref[0][0]) + + (-r*sprite_ref[0][0] + virtual_ref[0][0])*(-vop_ref[0][1]) + + (1<<(alpha+rho-1)); + s->sprite_offset[1][0]= ( (-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][0] + 1) + +( r*sprite_ref[0][1] - virtual_ref[0][1])*(-2*vop_ref[0][1] + 1) + +2*w2*r*sprite_ref[0][0] + - 16*w2 + + (1<<(alpha+rho+1))); + s->sprite_offset[1][1]= ( (-r*sprite_ref[0][1] + virtual_ref[0][1])*(-2*vop_ref[0][0] + 1) + +(-r*sprite_ref[0][0] + virtual_ref[0][0])*(-2*vop_ref[0][1] + 1) + +2*w2*r*sprite_ref[0][1] + - 16*w2 + + (1<<(alpha+rho+1))); + s->sprite_delta[0][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); + s->sprite_delta[0][1]= (+r*sprite_ref[0][1] - virtual_ref[0][1]); + s->sprite_delta[1][0]= (-r*sprite_ref[0][1] + virtual_ref[0][1]); + s->sprite_delta[1][1]= (-r*sprite_ref[0][0] + virtual_ref[0][0]); + + s->sprite_shift[0]= alpha+rho; + s->sprite_shift[1]= alpha+rho+2; break; -// case 3: + case 3: + min_ab= MIN(alpha, beta); + w3= w2>>min_ab; + h3= h2>>min_ab; + s->sprite_offset[0][0]= (sprite_ref[0][0]<<(alpha+beta+rho-min_ab)) + + (-r*sprite_ref[0][0] + virtual_ref[0][0])*h3*(-vop_ref[0][0]) + + (-r*sprite_ref[0][0] + virtual_ref[1][0])*w3*(-vop_ref[0][1]) + + (1<<(alpha+beta+rho-min_ab-1)); + s->sprite_offset[0][1]= (sprite_ref[0][1]<<(alpha+beta+rho-min_ab)) + + (-r*sprite_ref[0][1] + virtual_ref[0][1])*h3*(-vop_ref[0][0]) + + (-r*sprite_ref[0][1] + virtual_ref[1][1])*w3*(-vop_ref[0][1]) + + (1<<(alpha+beta+rho-min_ab-1)); + s->sprite_offset[1][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0])*h3*(-2*vop_ref[0][0] + 1) + + (-r*sprite_ref[0][0] + virtual_ref[1][0])*w3*(-2*vop_ref[0][1] + 1) + + 2*w2*h3*r*sprite_ref[0][0] + - 16*w2*h3 + + (1<<(alpha+beta+rho-min_ab+1)); + s->sprite_offset[1][1]= (-r*sprite_ref[0][1] + virtual_ref[0][1])*h3*(-2*vop_ref[0][0] + 1) + + (-r*sprite_ref[0][1] + virtual_ref[1][1])*w3*(-2*vop_ref[0][1] + 1) + + 2*w2*h3*r*sprite_ref[0][1] + - 16*w2*h3 + + (1<<(alpha+beta+rho-min_ab+1)); + s->sprite_delta[0][0]= (-r*sprite_ref[0][0] + virtual_ref[0][0])*h3; + s->sprite_delta[0][1]= (-r*sprite_ref[0][0] + virtual_ref[1][0])*w3; + s->sprite_delta[1][0]= (-r*sprite_ref[0][1] + virtual_ref[0][1])*h3; + s->sprite_delta[1][1]= (-r*sprite_ref[0][1] + virtual_ref[1][1])*w3; + + s->sprite_shift[0]= alpha + beta + rho - min_ab; + s->sprite_shift[1]= alpha + beta + rho - min_ab + 2; break; } -/*printf("%d %d\n", s->sprite_delta[0][0][0], a<sprite_shift[0][0]); -printf("%d %d\n", s->sprite_delta[0][0][1], 0); -printf("%d %d\n", s->sprite_delta[0][1][0], 0); -printf("%d %d\n", s->sprite_delta[0][1][1], a<sprite_shift[0][1]); -printf("%d %d\n", s->sprite_delta[1][0][0], a<sprite_shift[1][0]); -printf("%d %d\n", s->sprite_delta[1][0][1], 0); -printf("%d %d\n", s->sprite_delta[1][1][0], 0); -printf("%d %d\n", s->sprite_delta[1][1][1], a<sprite_shift[1][1]);*/ /* try to simplify the situation */ - if( s->sprite_delta[0][0][0] == a<sprite_shift[0][0] - && s->sprite_delta[0][0][1] == 0 - && s->sprite_delta[0][1][0] == 0 - && s->sprite_delta[0][1][1] == a<sprite_shift[0][1] - && s->sprite_delta[1][0][0] == a<sprite_shift[1][0] - && s->sprite_delta[1][0][1] == 0 - && s->sprite_delta[1][1][0] == 0 - && s->sprite_delta[1][1][1] == a<sprite_shift[1][1]) + if( s->sprite_delta[0][0] == a<sprite_shift[0] + && s->sprite_delta[0][1] == 0 + && s->sprite_delta[1][0] == 0 + && s->sprite_delta[1][1] == a<sprite_shift[0]) { - s->sprite_offset[0][0]>>=s->sprite_shift[0][0]; - s->sprite_offset[0][1]>>=s->sprite_shift[0][1]; - s->sprite_offset[1][0]>>=s->sprite_shift[1][0]; - s->sprite_offset[1][1]>>=s->sprite_shift[1][1]; - s->sprite_delta[0][0][0]= a; - s->sprite_delta[0][0][1]= 0; - s->sprite_delta[0][1][0]= 0; - s->sprite_delta[0][1][1]= a; - s->sprite_delta[1][0][0]= a; - s->sprite_delta[1][0][1]= 0; - s->sprite_delta[1][1][0]= 0; - s->sprite_delta[1][1][1]= a; - s->sprite_shift[0][0]= 0; - s->sprite_shift[0][1]= 0; - s->sprite_shift[1][0]= 0; - s->sprite_shift[1][1]= 0; + s->sprite_offset[0][0]>>=s->sprite_shift[0]; + s->sprite_offset[0][1]>>=s->sprite_shift[0]; + s->sprite_offset[1][0]>>=s->sprite_shift[1]; + s->sprite_offset[1][1]>>=s->sprite_shift[1]; + s->sprite_delta[0][0]= a; + s->sprite_delta[0][1]= 0; + s->sprite_delta[1][0]= 0; + s->sprite_delta[1][1]= a; + s->sprite_shift[0]= 0; + s->sprite_shift[1]= 0; s->real_sprite_warping_points=1; } - else + else{ + int shift_y= 16 - s->sprite_shift[0]; + int shift_c= 16 - s->sprite_shift[1]; +//printf("shifts %d %d\n", shift_y, shift_c); + for(i=0; i<2; i++){ + s->sprite_offset[0][i]<<= shift_y; + s->sprite_offset[1][i]<<= shift_c; + s->sprite_delta[0][i]<<= shift_y; + s->sprite_delta[1][i]<<= shift_y; + s->sprite_shift[i]= 16; + } s->real_sprite_warping_points= s->num_sprite_warping_points; - -//printf("%d %d %d %d\n", d[0][0], d[0][1], s->sprite_offset[0][0], s->sprite_offset[0][1]); + } +#if 0 +printf("vop:%d:%d %d:%d %d:%d, sprite:%d:%d %d:%d %d:%d, virtual: %d:%d %d:%d\n", + vop_ref[0][0], vop_ref[0][1], + vop_ref[1][0], vop_ref[1][1], + vop_ref[2][0], vop_ref[2][1], + sprite_ref[0][0], sprite_ref[0][1], + sprite_ref[1][0], sprite_ref[1][1], + sprite_ref[2][0], sprite_ref[2][1], + virtual_ref[0][0], virtual_ref[0][1], + virtual_ref[1][0], virtual_ref[1][1] + ); + +printf("offset: %d:%d , delta: %d %d %d %d, shift %d\n", + s->sprite_offset[0][0], s->sprite_offset[0][1], + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + s->sprite_shift[0] + ); +#endif } static int decode_vol_header(MpegEncContext *s, GetBitContext *gb){ @@ -4337,8 +4363,7 @@ printf("low_delay flag set, but shouldnt, clearing it\n"); s->low_delay=0; } -// printf("pic: %d, qpel:%d part:%d resync:%d\n", s->pict_type, s->quarter_sample, s->data_partitioning, s->resync_marker); - + s->partitioned_frame= s->data_partitioning && s->pict_type!=B_TYPE; if(s->partitioned_frame) s->decode_mb= mpeg4_decode_partitioned_mb; @@ -4483,11 +4508,12 @@ }else s->b_code=1; #if 0 -printf("qp:%d fc:%d bc:%d type:%s size:%d pro:%d alt:%d top:%d qpel:%d part:%d resync:%d\n", +printf("qp:%d fc:%d bc:%d type:%s size:%d pro:%d alt:%d top:%d qpel:%d part:%d resync:%d w:%d a:%d\n", s->qscale, s->f_code, s->b_code, s->pict_type == I_TYPE ? "I" : (s->pict_type == P_TYPE ? "P" : (s->pict_type == B_TYPE ? "B" : "S")), gb->size,s->progressive_sequence, s->alternate_scan, s->top_field_first, - s->quarter_sample, s->data_partitioning, s->resync_marker); + s->quarter_sample, s->data_partitioning, s->resync_marker, s->num_sprite_warping_points, + s->sprite_warping_accuracy); #endif if(!s->scalability){ if (s->shape!=RECT_SHAPE && s->pict_type!=I_TYPE) { diff -r 97077dd24bfa -r 8e1f0939d15d mpegvideo.c --- a/mpegvideo.c Wed Oct 16 17:23:18 2002 +0000 +++ b/mpegvideo.c Wed Oct 16 19:55:49 2002 +0000 @@ -1032,15 +1032,13 @@ static inline void gmc1_motion(MpegEncContext *s, UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, int dest_offset, - UINT8 **ref_picture, int src_offset, - int h) + UINT8 **ref_picture, int src_offset) { UINT8 *ptr; int offset, src_x, src_y, linesize, uvlinesize; int motion_x, motion_y; int emu=0; - if(s->real_sprite_warping_points>1) printf("more than 1 warp point isnt supported\n"); motion_x= s->sprite_offset[0][0]; motion_y= s->sprite_offset[0][1]; src_x = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy+1)); @@ -1053,22 +1051,37 @@ src_y = clip(src_y, -16, s->height); if (src_y == s->height) motion_y =0; - + linesize = s->linesize; uvlinesize = s->uvlinesize; + ptr = ref_picture[0] + (src_y * linesize) + src_x + src_offset; dest_y+=dest_offset; if(s->flags&CODEC_FLAG_EMU_EDGE){ if(src_x<0 || src_y<0 || src_x + (motion_x&15) + 16 > s->h_edge_pos - || src_y + (motion_y&15) + h > s->v_edge_pos){ - emulated_edge_mc(s, ptr, linesize, 17, h+1, src_x, src_y, s->h_edge_pos, s->v_edge_pos); + || src_y + (motion_y&15) + 16 > s->v_edge_pos){ + emulated_edge_mc(s, ptr, linesize, 17, 17, src_x, src_y, s->h_edge_pos, s->v_edge_pos); ptr= s->edge_emu_buffer; emu=1; } } - gmc1(dest_y , ptr , linesize, h, motion_x&15, motion_y&15, s->no_rounding); - gmc1(dest_y+8, ptr+8, linesize, h, motion_x&15, motion_y&15, s->no_rounding); + + if((motion_x|motion_y)&7){ + ff_gmc1(dest_y , ptr , linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding); + ff_gmc1(dest_y+8, ptr+8, linesize, 16, motion_x&15, motion_y&15, 128 - s->no_rounding); + }else{ + int dxy; + + dxy= ((motion_x>>3)&1) | ((motion_y>>2)&2); + if (s->no_rounding){ + put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16); + }else{ + put_pixels_tab [0][dxy](dest_y, ptr, linesize, 16); + } + } + + if(s->flags&CODEC_FLAG_GRAY) return; motion_x= s->sprite_offset[1][0]; motion_y= s->sprite_offset[1][1]; @@ -1086,21 +1099,85 @@ offset = (src_y * uvlinesize) + src_x + (src_offset>>1); ptr = ref_picture[1] + offset; if(emu){ - emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); + emulated_edge_mc(s, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } - gmc1(dest_cb + (dest_offset>>1), ptr, uvlinesize, h>>1, motion_x&15, motion_y&15, s->no_rounding); + ff_gmc1(dest_cb + (dest_offset>>1), ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); ptr = ref_picture[2] + offset; if(emu){ - emulated_edge_mc(s, ptr, uvlinesize, 9, (h>>1)+1, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); + emulated_edge_mc(s, ptr, uvlinesize, 9, 9, src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); ptr= s->edge_emu_buffer; } - gmc1(dest_cr + (dest_offset>>1), ptr, uvlinesize, h>>1, motion_x&15, motion_y&15, s->no_rounding); + ff_gmc1(dest_cr + (dest_offset>>1), ptr, uvlinesize, 8, motion_x&15, motion_y&15, 128 - s->no_rounding); return; } +static inline void gmc_motion(MpegEncContext *s, + UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, + int dest_offset, + UINT8 **ref_picture, int src_offset) +{ + UINT8 *ptr; + int linesize, uvlinesize; + const int a= s->sprite_warping_accuracy; + int ox, oy; + + linesize = s->linesize; + uvlinesize = s->uvlinesize; + + ptr = ref_picture[0] + src_offset; + + dest_y+=dest_offset; + + ox= s->sprite_offset[0][0] + s->sprite_delta[0][0]*s->mb_x*16 + s->sprite_delta[0][1]*s->mb_y*16; + oy= s->sprite_offset[0][1] + s->sprite_delta[1][0]*s->mb_x*16 + s->sprite_delta[1][1]*s->mb_y*16; + + ff_gmc(dest_y, ptr, linesize, 16, + ox, + oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos, s->v_edge_pos); + ff_gmc(dest_y+8, ptr, linesize, 16, + ox + s->sprite_delta[0][0]*8, + oy + s->sprite_delta[1][0]*8, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos, s->v_edge_pos); + + if(s->flags&CODEC_FLAG_GRAY) return; + + + dest_cb+=dest_offset>>1; + dest_cr+=dest_offset>>1; + + ox= s->sprite_offset[1][0] + s->sprite_delta[0][0]*s->mb_x*8 + s->sprite_delta[0][1]*s->mb_y*8; + oy= s->sprite_offset[1][1] + s->sprite_delta[1][0]*s->mb_x*8 + s->sprite_delta[1][1]*s->mb_y*8; + + ptr = ref_picture[1] + (src_offset>>1); + ff_gmc(dest_cb, ptr, uvlinesize, 8, + ox, + oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos>>1, s->v_edge_pos>>1); + + ptr = ref_picture[2] + (src_offset>>1); + ff_gmc(dest_cr, ptr, uvlinesize, 8, + ox, + oy, + s->sprite_delta[0][0], s->sprite_delta[0][1], + s->sprite_delta[1][0], s->sprite_delta[1][1], + a+1, (1<<(2*a+1)) - s->no_rounding, + s->h_edge_pos>>1, s->v_edge_pos>>1); +} + + static void emulated_edge_mc(MpegEncContext *s, UINT8 *src, int linesize, int block_w, int block_h, int src_x, int src_y, int w, int h){ int x, y; @@ -1357,9 +1434,13 @@ switch(s->mv_type) { case MV_TYPE_16X16: if(s->mcsel){ - gmc1_motion(s, dest_y, dest_cb, dest_cr, 0, - ref_picture, 0, - 16); + if(s->real_sprite_warping_points==1){ + gmc1_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, 0); + }else{ + gmc_motion(s, dest_y, dest_cb, dest_cr, 0, + ref_picture, 0); + } }else if(s->quarter_sample){ qpel_motion(s, dest_y, dest_cb, dest_cr, 0, ref_picture, 0, diff -r 97077dd24bfa -r 8e1f0939d15d mpegvideo.h --- a/mpegvideo.h Wed Oct 16 17:23:18 2002 +0000 +++ b/mpegvideo.h Wed Oct 16 19:55:49 2002 +0000 @@ -369,9 +369,9 @@ int sprite_brightness_change; int num_sprite_warping_points; int real_sprite_warping_points; - int sprite_offset[2][2]; - int sprite_delta[2][2][2]; - int sprite_shift[2][2]; + int sprite_offset[2][2]; /* sprite offset[isChroma][isMVY] */ + int sprite_delta[2][2]; /* sprite_delta [isY][isMVY] */ + int sprite_shift[2]; /* sprite shift [isChroma] */ int mcsel; int quant_precision; int quarter_sample; /* 1->qpel, 0->half pel ME/MC */