mirror of https://github.com/FFmpeg/FFmpeg.git
4mv+b frames encoding finally fixed chroma ME 5 comparission functions for ME b frame encoding speedup wmv2 codec (unfinished) user specified diamond size for EPZS Originally committed as revision 1365 to svn://svn.ffmpeg.org/ffmpeg/trunkpull/126/head
parent
ac97734133
commit
1457ab5233
18 changed files with 3213 additions and 970 deletions
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,737 @@ |
||||
/*
|
||||
* Motion estimation
|
||||
* Copyright (c) 2002 Michael Niedermayer |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
* |
||||
*/ |
||||
|
||||
//lets hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
|
||||
//Note, the last line is there to kill these ugly unused var warnings
|
||||
#define LOAD_COMMON(x, y)\ |
||||
uint32_t * const score_map= s->me.score_map;\
|
||||
const int stride= s->linesize;\
|
||||
const int uvstride= s->uvlinesize;\
|
||||
const int time_pp= s->pp_time;\
|
||||
const int time_pb= s->pb_time;\
|
||||
uint8_t * const src_y= s->new_picture.data[0] + ((y) * stride) + (x);\
|
||||
uint8_t * const src_u= s->new_picture.data[1] + (((y)>>1) * uvstride) + ((x)>>1);\
|
||||
uint8_t * const src_v= s->new_picture.data[2] + (((y)>>1) * uvstride) + ((x)>>1);\
|
||||
uint8_t * const ref_y= ref_picture->data[0] + ((y) * stride) + (x);\
|
||||
uint8_t * const ref_u= ref_picture->data[1] + (((y)>>1) * uvstride) + ((x)>>1);\
|
||||
uint8_t * const ref_v= ref_picture->data[2] + (((y)>>1) * uvstride) + ((x)>>1);\
|
||||
uint8_t * const ref2_y= s->next_picture.data[0] + ((y) * stride) + (x);\
|
||||
op_pixels_func (*hpel_put)[4];\
|
||||
op_pixels_func (*hpel_avg)[4]= &s->dsp.avg_pixels_tab[size];\
|
||||
op_pixels_func (*chroma_hpel_put)[4];\
|
||||
qpel_mc_func (*qpel_put)[16];\
|
||||
qpel_mc_func (*qpel_avg)[16]= &s->dsp.avg_qpel_pixels_tab[size];\
|
||||
const __attribute__((unused)) int unu= time_pp + time_pb + (int)src_u + (int)src_v + (int)ref_u + (int)ref_v\
|
||||
+ (int)ref2_y + (int)hpel_avg + (int)qpel_avg;\
|
||||
if(s->no_rounding /*FIXME b_type*/){\
|
||||
hpel_put= &s->dsp.put_no_rnd_pixels_tab[size];\
|
||||
chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1];\
|
||||
qpel_put= &s->dsp.put_no_rnd_qpel_pixels_tab[size];\
|
||||
}else{\
|
||||
hpel_put=& s->dsp.put_pixels_tab[size];\
|
||||
chroma_hpel_put= &s->dsp.put_pixels_tab[size+1];\
|
||||
qpel_put= &s->dsp.put_qpel_pixels_tab[size];\
|
||||
} |
||||
|
||||
|
||||
#ifdef CMP_HPEL |
||||
|
||||
#define CHECK_HALF_MV(dx, dy, x, y)\ |
||||
{\
|
||||
const int hx= 2*(x)+(dx);\
|
||||
const int hy= 2*(y)+(dy);\
|
||||
CMP_HPEL(d, dx, dy, x, y, size);\
|
||||
d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
|
||||
COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
|
||||
} |
||||
|
||||
#if 0 |
||||
static int RENAME(hpel_motion_search)(MpegEncContext * s, |
||||
int *mx_ptr, int *my_ptr, int dmin, |
||||
int xmin, int ymin, int xmax, int ymax, |
||||
int pred_x, int pred_y, Picture *ref_picture,
|
||||
int n, int size) |
||||
{ |
||||
UINT8 *ptr; |
||||
|
||||
const int xx = 16 * s->mb_x + 8*(n&1); |
||||
const int yy = 16 * s->mb_y + 8*(n>>1); |
||||
const int mx = *mx_ptr; |
||||
const int my = *my_ptr; |
||||
|
||||
LOAD_COMMON(xx, yy); |
||||
|
||||
// INIT;
|
||||
//FIXME factorize
|
||||
me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub; |
||||
|
||||
if(s->no_rounding /*FIXME b_type*/){ |
||||
hpel_put= &s->dsp.put_no_rnd_pixels_tab[size]; |
||||
chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1]; |
||||
}else{ |
||||
hpel_put=& s->dsp.put_pixels_tab[size]; |
||||
chroma_hpel_put= &s->dsp.put_pixels_tab[size+1]; |
||||
} |
||||
cmp= s->dsp.me_cmp[size]; |
||||
chroma_cmp= s->dsp.me_cmp[size+1]; |
||||
cmp_sub= s->dsp.me_sub_cmp[size]; |
||||
chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; |
||||
|
||||
if(s->me.skip){ //FIXME somehow move up (benchmark)
|
||||
*mx_ptr = 0; |
||||
*my_ptr = 0; |
||||
return dmin; |
||||
} |
||||
|
||||
if(s->avctx->me_cmp != s->avctx->me_sub_cmp){ |
||||
CMP_HPEL(dmin, 0, 0, mx, my, size); |
||||
if(mx || my) |
||||
dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; |
||||
} |
||||
|
||||
if (mx > xmin && mx < xmax &&
|
||||
my > ymin && my < ymax) { |
||||
int bx=2*mx, by=2*my; |
||||
int d= dmin; |
||||
|
||||
CHECK_HALF_MV(1, 1, mx-1, my-1) |
||||
CHECK_HALF_MV(0, 1, mx , my-1)
|
||||
CHECK_HALF_MV(1, 1, mx , my-1) |
||||
CHECK_HALF_MV(1, 0, mx-1, my ) |
||||
CHECK_HALF_MV(1, 0, mx , my ) |
||||
CHECK_HALF_MV(1, 1, mx-1, my ) |
||||
CHECK_HALF_MV(0, 1, mx , my )
|
||||
CHECK_HALF_MV(1, 1, mx , my ) |
||||
|
||||
assert(bx < xmin*2 || bx > xmax*2 || by < ymin*2 || by > ymax*2); |
||||
|
||||
*mx_ptr = bx; |
||||
*my_ptr = by; |
||||
}else{ |
||||
*mx_ptr =2*mx; |
||||
*my_ptr =2*my; |
||||
} |
||||
|
||||
return dmin; |
||||
} |
||||
|
||||
#else |
||||
static int RENAME(hpel_motion_search)(MpegEncContext * s, |
||||
int *mx_ptr, int *my_ptr, int dmin, |
||||
int xmin, int ymin, int xmax, int ymax, |
||||
int pred_x, int pred_y, Picture *ref_picture,
|
||||
int n, int size, uint16_t * const mv_penalty) |
||||
{ |
||||
const int xx = 16 * s->mb_x + 8*(n&1); |
||||
const int yy = 16 * s->mb_y + 8*(n>>1); |
||||
const int mx = *mx_ptr; |
||||
const int my = *my_ptr;
|
||||
const int penalty_factor= s->me.sub_penalty_factor; |
||||
me_cmp_func cmp_sub, chroma_cmp_sub; |
||||
|
||||
LOAD_COMMON(xx, yy); |
||||
|
||||
//FIXME factorize
|
||||
|
||||
cmp_sub= s->dsp.me_sub_cmp[size]; |
||||
chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; |
||||
|
||||
if(s->me.skip){ //FIXME move out of hpel?
|
||||
*mx_ptr = 0; |
||||
*my_ptr = 0; |
||||
return dmin; |
||||
} |
||||
|
||||
if(s->avctx->me_cmp != s->avctx->me_sub_cmp){ |
||||
CMP_HPEL(dmin, 0, 0, mx, my, size); |
||||
if(mx || my) |
||||
dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; |
||||
} |
||||
|
||||
if (mx > xmin && mx < xmax &&
|
||||
my > ymin && my < ymax) { |
||||
int bx=2*mx, by=2*my; |
||||
int d= dmin; |
||||
const int index= (my<<ME_MAP_SHIFT) + mx; |
||||
const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
|
||||
+ (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*penalty_factor; |
||||
const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)] |
||||
+ (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*penalty_factor; |
||||
const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)] |
||||
+ (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*penalty_factor; |
||||
const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] |
||||
+ (mv_penalty[bx - pred_x] + mv_penalty[by+2 - pred_y])*penalty_factor; |
||||
|
||||
if(t<=b){ |
||||
CHECK_HALF_MV(0, 1, mx ,my-1) |
||||
if(l<=r){ |
||||
CHECK_HALF_MV(1, 1, mx-1, my-1) |
||||
if(t+r<=b+l){ |
||||
CHECK_HALF_MV(1, 1, mx , my-1) |
||||
}else{ |
||||
CHECK_HALF_MV(1, 1, mx-1, my ) |
||||
} |
||||
CHECK_HALF_MV(1, 0, mx-1, my ) |
||||
}else{ |
||||
CHECK_HALF_MV(1, 1, mx , my-1) |
||||
if(t+l<=b+r){ |
||||
CHECK_HALF_MV(1, 1, mx-1, my-1) |
||||
}else{ |
||||
CHECK_HALF_MV(1, 1, mx , my ) |
||||
} |
||||
CHECK_HALF_MV(1, 0, mx , my ) |
||||
} |
||||
}else{ |
||||
if(l<=r){ |
||||
if(t+l<=b+r){ |
||||
CHECK_HALF_MV(1, 1, mx-1, my-1) |
||||
}else{ |
||||
CHECK_HALF_MV(1, 1, mx , my ) |
||||
} |
||||
CHECK_HALF_MV(1, 0, mx-1, my) |
||||
CHECK_HALF_MV(1, 1, mx-1, my) |
||||
}else{ |
||||
if(t+r<=b+l){ |
||||
CHECK_HALF_MV(1, 1, mx , my-1) |
||||
}else{ |
||||
CHECK_HALF_MV(1, 1, mx-1, my) |
||||
} |
||||
CHECK_HALF_MV(1, 0, mx , my) |
||||
CHECK_HALF_MV(1, 1, mx , my) |
||||
} |
||||
CHECK_HALF_MV(0, 1, mx , my) |
||||
} |
||||
assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2); |
||||
|
||||
*mx_ptr = bx; |
||||
*my_ptr = by; |
||||
}else{ |
||||
*mx_ptr =2*mx; |
||||
*my_ptr =2*my; |
||||
} |
||||
|
||||
return dmin; |
||||
} |
||||
#endif |
||||
|
||||
#endif /* CMP_HPEL */ |
||||
|
||||
#ifdef CMP_QPEL |
||||
|
||||
#define CHECK_QUARTER_MV(dx, dy, x, y)\ |
||||
{\
|
||||
const int hx= 4*(x)+(dx);\
|
||||
const int hy= 4*(y)+(dy);\
|
||||
CMP_QPEL(d, dx, dy, x, y, size);\
|
||||
d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
|
||||
COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
|
||||
} |
||||
|
||||
static int RENAME(qpel_motion_search)(MpegEncContext * s, |
||||
int *mx_ptr, int *my_ptr, int dmin, |
||||
int xmin, int ymin, int xmax, int ymax, |
||||
int pred_x, int pred_y, Picture *ref_picture,
|
||||
int n, int size, uint16_t * const mv_penalty) |
||||
{ |
||||
const int xx = 16 * s->mb_x + 8*(n&1); |
||||
const int yy = 16 * s->mb_y + 8*(n>>1); |
||||
const int mx = *mx_ptr; |
||||
const int my = *my_ptr;
|
||||
const int penalty_factor= s->me.sub_penalty_factor; |
||||
const int map_generation= s->me.map_generation; |
||||
uint32_t *map= s->me.map; |
||||
me_cmp_func cmp, chroma_cmp; |
||||
me_cmp_func cmp_sub, chroma_cmp_sub; |
||||
|
||||
LOAD_COMMON(xx, yy); |
||||
|
||||
cmp= s->dsp.me_cmp[size]; |
||||
chroma_cmp= s->dsp.me_cmp[size+1]; //factorize FIXME
|
||||
//FIXME factorize
|
||||
|
||||
cmp_sub= s->dsp.me_sub_cmp[size]; |
||||
chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; |
||||
|
||||
if(s->me.skip){ //FIXME somehow move up (benchmark)
|
||||
*mx_ptr = 0; |
||||
*my_ptr = 0; |
||||
return dmin; |
||||
} |
||||
|
||||
if(s->avctx->me_cmp != s->avctx->me_sub_cmp){ |
||||
CMP_QPEL(dmin, 0, 0, mx, my, size); |
||||
if(mx || my) |
||||
dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor; |
||||
} |
||||
|
||||
if (mx > xmin && mx < xmax &&
|
||||
my > ymin && my < ymax) { |
||||
int bx=4*mx, by=4*my; |
||||
int d= dmin; |
||||
int i, nx, ny; |
||||
const int index= (my<<ME_MAP_SHIFT) + mx; |
||||
const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)]; |
||||
const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]; |
||||
const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)]; |
||||
const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)]; |
||||
const int c= score_map[(index )&(ME_MAP_SIZE-1)]; |
||||
int best[8]; |
||||
int best_pos[8][2]; |
||||
|
||||
memset(best, 64, sizeof(int)*8); |
||||
#if 1 |
||||
if(s->avctx->dia_size>=2){
|
||||
const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
||||
const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
||||
const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; |
||||
const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; |
||||
|
||||
for(ny= -3; ny <= 3; ny++){ |
||||
for(nx= -3; nx <= 3; nx++){ |
||||
const int t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t; |
||||
const int c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c; |
||||
const int b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b; |
||||
int score= ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2; |
||||
int i; |
||||
|
||||
if((nx&3)==0 && (ny&3)==0) continue; |
||||
|
||||
score += 1024*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor; |
||||
|
||||
// if(nx&1) score-=1024*s->me.penalty_factor;
|
||||
// if(ny&1) score-=1024*s->me.penalty_factor;
|
||||
|
||||
for(i=0; i<8; i++){ |
||||
if(score < best[i]){ |
||||
memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); |
||||
memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); |
||||
best[i]= score; |
||||
best_pos[i][0]= nx + 4*mx; |
||||
best_pos[i][1]= ny + 4*my; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}else{ |
||||
int tl; |
||||
const int cx = 4*(r - l); |
||||
const int cx2= r + l - 2*c;
|
||||
const int cy = 4*(b - t); |
||||
const int cy2= b + t - 2*c; |
||||
int cxy; |
||||
|
||||
if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
|
||||
tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
||||
}else{ |
||||
CMP(tl, mx-1, my-1, size); //FIXME wrong if chroma me is different
|
||||
} |
||||
|
||||
cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
|
||||
|
||||
assert(16*cx2 + 4*cx + 32*c == 32*r); |
||||
assert(16*cx2 - 4*cx + 32*c == 32*l); |
||||
assert(16*cy2 + 4*cy + 32*c == 32*b); |
||||
assert(16*cy2 - 4*cy + 32*c == 32*t); |
||||
assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl); |
||||
|
||||
for(ny= -3; ny <= 3; ny++){ |
||||
for(nx= -3; nx <= 3; nx++){ |
||||
int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
|
||||
int i; |
||||
|
||||
if((nx&3)==0 && (ny&3)==0) continue; |
||||
|
||||
score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor; |
||||
// if(nx&1) score-=32*s->me.penalty_factor;
|
||||
// if(ny&1) score-=32*s->me.penalty_factor;
|
||||
|
||||
for(i=0; i<8; i++){ |
||||
if(score < best[i]){ |
||||
memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); |
||||
memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); |
||||
best[i]= score; |
||||
best_pos[i][0]= nx + 4*mx; |
||||
best_pos[i][1]= ny + 4*my; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
}
|
||||
} |
||||
for(i=0; i<8; i++){ |
||||
nx= best_pos[i][0]; |
||||
ny= best_pos[i][1]; |
||||
CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2) |
||||
} |
||||
#if 0 |
||||
nx= FFMAX(4*mx - bx, bx - 4*mx); |
||||
ny= FFMAX(4*my - by, by - 4*my); |
||||
|
||||
static int stats[4][4]; |
||||
stats[nx][ny]++; |
||||
if(256*256*256*64 % (stats[0][0]+1) ==0){ |
||||
for(i=0; i<16; i++){ |
||||
if((i&3)==0) printf("\n"); |
||||
printf("%6d ", stats[0][i]); |
||||
} |
||||
printf("\n"); |
||||
} |
||||
#endif |
||||
#else |
||||
|
||||
CHECK_QUARTER_MV(2, 2, mx-1, my-1) |
||||
CHECK_QUARTER_MV(0, 2, mx , my-1)
|
||||
CHECK_QUARTER_MV(2, 2, mx , my-1) |
||||
CHECK_QUARTER_MV(2, 0, mx , my ) |
||||
CHECK_QUARTER_MV(2, 2, mx , my ) |
||||
CHECK_QUARTER_MV(0, 2, mx , my ) |
||||
CHECK_QUARTER_MV(2, 2, mx-1, my ) |
||||
CHECK_QUARTER_MV(2, 0, mx-1, my ) |
||||
|
||||
nx= bx; |
||||
ny= by; |
||||
|
||||
for(i=0; i<8; i++){ |
||||
int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1}; |
||||
int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1}; |
||||
CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2) |
||||
} |
||||
#endif |
||||
#if 0 |
||||
//outer ring
|
||||
CHECK_QUARTER_MV(1, 3, mx-1, my-1) |
||||
CHECK_QUARTER_MV(1, 2, mx-1, my-1) |
||||
CHECK_QUARTER_MV(1, 1, mx-1, my-1) |
||||
CHECK_QUARTER_MV(2, 1, mx-1, my-1) |
||||
CHECK_QUARTER_MV(3, 1, mx-1, my-1) |
||||
CHECK_QUARTER_MV(0, 1, mx , my-1) |
||||
CHECK_QUARTER_MV(1, 1, mx , my-1) |
||||
CHECK_QUARTER_MV(2, 1, mx , my-1) |
||||
CHECK_QUARTER_MV(3, 1, mx , my-1) |
||||
CHECK_QUARTER_MV(3, 2, mx , my-1) |
||||
CHECK_QUARTER_MV(3, 3, mx , my-1) |
||||
CHECK_QUARTER_MV(3, 0, mx , my ) |
||||
CHECK_QUARTER_MV(3, 1, mx , my ) |
||||
CHECK_QUARTER_MV(3, 2, mx , my ) |
||||
CHECK_QUARTER_MV(3, 3, mx , my ) |
||||
CHECK_QUARTER_MV(2, 3, mx , my ) |
||||
CHECK_QUARTER_MV(1, 3, mx , my ) |
||||
CHECK_QUARTER_MV(0, 3, mx , my ) |
||||
CHECK_QUARTER_MV(3, 3, mx-1, my ) |
||||
CHECK_QUARTER_MV(2, 3, mx-1, my ) |
||||
CHECK_QUARTER_MV(1, 3, mx-1, my ) |
||||
CHECK_QUARTER_MV(1, 2, mx-1, my ) |
||||
CHECK_QUARTER_MV(1, 1, mx-1, my ) |
||||
CHECK_QUARTER_MV(1, 0, mx-1, my ) |
||||
#endif |
||||
assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4); |
||||
|
||||
*mx_ptr = bx; |
||||
*my_ptr = by; |
||||
}else{ |
||||
*mx_ptr =4*mx; |
||||
*my_ptr =4*my; |
||||
} |
||||
|
||||
return dmin; |
||||
} |
||||
|
||||
#endif /* CMP_QPEL */ |
||||
|
||||
#define CHECK_MV(x,y)\ |
||||
{\
|
||||
const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
|
||||
const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
|
||||
if(map[index]!=key){\
|
||||
CMP(d, x, y, size);\
|
||||
map[index]= key;\
|
||||
score_map[index]= d;\
|
||||
d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
|
||||
COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
|
||||
}\
|
||||
} |
||||
|
||||
#define CHECK_MV_DIR(x,y,new_dir)\ |
||||
{\
|
||||
const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
|
||||
const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
|
||||
if(map[index]!=key){\
|
||||
CMP(d, x, y, size);\
|
||||
map[index]= key;\
|
||||
score_map[index]= d;\
|
||||
d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
|
||||
if(d<dmin){\
|
||||
best[0]=x;\
|
||||
best[1]=y;\
|
||||
dmin=d;\
|
||||
next_dir= new_dir;\
|
||||
}\
|
||||
}\
|
||||
} |
||||
|
||||
#define check(x,y,S,v)\ |
||||
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
|
||||
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
|
||||
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
|
||||
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
|
||||
|
||||
|
||||
static inline int RENAME(small_diamond_search)(MpegEncContext * s, int *best, int dmin, |
||||
Picture *ref_picture, |
||||
int const pred_x, int const pred_y, int const penalty_factor, |
||||
int const xmin, int const ymin, int const xmax, int const ymax, int const shift, |
||||
uint32_t *map, int map_generation, int size, uint16_t * const mv_penalty |
||||
) |
||||
{ |
||||
me_cmp_func cmp, chroma_cmp; |
||||
int next_dir=-1; |
||||
LOAD_COMMON(s->mb_x*16, s->mb_y*16); |
||||
|
||||
cmp= s->dsp.me_cmp[size]; |
||||
chroma_cmp= s->dsp.me_cmp[size+1]; |
||||
|
||||
for(;;){ |
||||
int d; |
||||
const int dir= next_dir; |
||||
const int x= best[0]; |
||||
const int y= best[1]; |
||||
next_dir=-1; |
||||
|
||||
//printf("%d", dir);
|
||||
if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0) |
||||
if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1) |
||||
if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2) |
||||
if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3) |
||||
|
||||
if(next_dir==-1){ |
||||
return dmin; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static inline int RENAME(var_diamond_search)(MpegEncContext * s, int *best, int dmin, |
||||
Picture *ref_picture, |
||||
int const pred_x, int const pred_y, int const penalty_factor, |
||||
int const xmin, int const ymin, int const xmax, int const ymax, int const shift, |
||||
uint32_t *map, int map_generation, int size, uint16_t * const mv_penalty |
||||
) |
||||
{ |
||||
me_cmp_func cmp, chroma_cmp; |
||||
int dia_size=1; |
||||
LOAD_COMMON(s->mb_x*16, s->mb_y*16); |
||||
|
||||
cmp= s->dsp.me_cmp[size]; |
||||
chroma_cmp= s->dsp.me_cmp[size+1]; |
||||
|
||||
for(dia_size=1; dia_size<=s->avctx->dia_size; dia_size++){ |
||||
int dir, start, end; |
||||
const int x= best[0]; |
||||
const int y= best[1]; |
||||
|
||||
start= FFMAX(0, y + dia_size - ymax); |
||||
end = FFMIN(dia_size, xmax - x); |
||||
for(dir= start; dir<end; dir++){ |
||||
int d; |
||||
|
||||
//check(x + dir,y + dia_size - dir,0, a0)
|
||||
CHECK_MV(x + dir , y + dia_size - dir); |
||||
} |
||||
|
||||
start= FFMAX(0, x + dia_size - xmax); |
||||
end = FFMIN(dia_size, y - ymin); |
||||
for(dir= start; dir<end; dir++){ |
||||
int d; |
||||
|
||||
//check(x + dia_size - dir, y - dir,0, a1)
|
||||
CHECK_MV(x + dia_size - dir, y - dir ); |
||||
} |
||||
|
||||
start= FFMAX(0, -y + dia_size + ymin ); |
||||
end = FFMIN(dia_size, x - xmin); |
||||
for(dir= start; dir<end; dir++){ |
||||
int d; |
||||
|
||||
//check(x - dir,y - dia_size + dir,0, a2)
|
||||
CHECK_MV(x - dir , y - dia_size + dir); |
||||
} |
||||
|
||||
start= FFMAX(0, -x + dia_size + xmin ); |
||||
end = FFMIN(dia_size, ymax - y); |
||||
for(dir= start; dir<end; dir++){ |
||||
int d; |
||||
|
||||
//check(x - dia_size + dir, y + dir,0, a3)
|
||||
CHECK_MV(x - dia_size + dir, y + dir ); |
||||
} |
||||
|
||||
if(x!=best[0] || y!=best[1]) |
||||
dia_size=0; |
||||
} |
||||
return dmin;
|
||||
} |
||||
|
||||
static int RENAME(epzs_motion_search)(MpegEncContext * s, int block, |
||||
int *mx_ptr, int *my_ptr, |
||||
int P[10][2], int pred_x, int pred_y, |
||||
int xmin, int ymin, int xmax, int ymax, Picture *ref_picture, uint16_t * const mv_penalty) |
||||
{ |
||||
int best[2]={0, 0}; |
||||
int d, dmin;
|
||||
const int shift= 1+s->quarter_sample; |
||||
uint32_t *map= s->me.map; |
||||
int map_generation; |
||||
const int penalty_factor= s->me.penalty_factor; |
||||
const int size=0; |
||||
me_cmp_func cmp, chroma_cmp; |
||||
LOAD_COMMON(s->mb_x*16, s->mb_y*16); |
||||
|
||||
cmp= s->dsp.me_cmp[size]; |
||||
chroma_cmp= s->dsp.me_cmp[size+1]; |
||||
|
||||
map_generation= update_map_generation(s); |
||||
|
||||
CMP(dmin, 0, 0, size); |
||||
map[0]= map_generation; |
||||
score_map[0]= dmin; |
||||
|
||||
/* first line */ |
||||
if ((s->mb_y == 0 || s->first_slice_line)) { |
||||
CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
||||
CHECK_MV(P_LAST[0]>>shift, P_LAST[1]>>shift) |
||||
}else{ |
||||
if(dmin<256 && ( P_LEFT[0] |P_LEFT[1] |
||||
|P_TOP[0] |P_TOP[1] |
||||
|P_TOPRIGHT[0]|P_TOPRIGHT[1])==0 && s->avctx->dia_size==0){ |
||||
*mx_ptr= 0; |
||||
*my_ptr= 0; |
||||
s->me.skip=1; |
||||
return dmin; |
||||
} |
||||
CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) |
||||
if(dmin>256*2){ |
||||
CHECK_MV(P_LAST[0] >>shift, P_LAST[1] >>shift) |
||||
CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift) |
||||
CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift) |
||||
CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) |
||||
} |
||||
} |
||||
if(dmin>256*4){ |
||||
CHECK_MV(P_LAST_RIGHT[0] >>shift, P_LAST_RIGHT[1] >>shift) |
||||
CHECK_MV(P_LAST_BOTTOM[0]>>shift, P_LAST_BOTTOM[1]>>shift) |
||||
} |
||||
#if 0 //doest only slow things down
|
||||
if(dmin>512*3){ |
||||
int step; |
||||
dmin= score_map[0]; |
||||
best[0]= best[1]=0; |
||||
for(step=128; step>0; step>>=1){ |
||||
const int step2= step; |
||||
int y; |
||||
for(y=-step2+best[1]; y<=step2+best[1]; y+=step){ |
||||
int x; |
||||
if(y<ymin || y>ymax) continue; |
||||
|
||||
for(x=-step2+best[0]; x<=step2+best[0]; x+=step){ |
||||
if(x<xmin || x>xmax) continue; |
||||
if(x==best[0] && y==best[1]) continue; |
||||
CHECK_MV(x,y) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
#endif |
||||
//check(best[0],best[1],0, b0)
|
||||
if(s->avctx->dia_size<2) |
||||
dmin= RENAME(small_diamond_search)(s, best, dmin, ref_picture, |
||||
pred_x, pred_y, penalty_factor, xmin, ymin, xmax, ymax,
|
||||
shift, map, map_generation, size, mv_penalty); |
||||
else |
||||
dmin= RENAME(var_diamond_search)(s, best, dmin, ref_picture, |
||||
pred_x, pred_y, penalty_factor, xmin, ymin, xmax, ymax,
|
||||
shift, map, map_generation, size, mv_penalty); |
||||
|
||||
//check(best[0],best[1],0, b1)
|
||||
*mx_ptr= best[0]; |
||||
*my_ptr= best[1];
|
||||
|
||||
// printf("%d %d %d \n", best[0], best[1], dmin);
|
||||
return dmin; |
||||
} |
||||
|
||||
#ifndef CMP_DIRECT /* no 4mv search needed in direct mode */ |
||||
static int RENAME(epzs_motion_search4)(MpegEncContext * s, int block, |
||||
int *mx_ptr, int *my_ptr, |
||||
int P[10][2], int pred_x, int pred_y, |
||||
int xmin, int ymin, int xmax, int ymax, Picture *ref_picture, uint16_t * const mv_penalty) |
||||
{ |
||||
int best[2]={0, 0}; |
||||
int d, dmin;
|
||||
const int shift= 1+s->quarter_sample; |
||||
uint32_t *map= s->me.map; |
||||
int map_generation; |
||||
const int penalty_factor= s->me.penalty_factor; |
||||
const int size=1; |
||||
me_cmp_func cmp, chroma_cmp; |
||||
LOAD_COMMON((s->mb_x*2 + (block&1))*8, (s->mb_y*2 + (block>>1))*8); |
||||
|
||||
cmp= s->dsp.me_cmp[size]; |
||||
chroma_cmp= s->dsp.me_cmp[size+1]; |
||||
|
||||
map_generation= update_map_generation(s); |
||||
|
||||
dmin = 1000000; |
||||
//printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
|
||||
/* first line */ |
||||
if ((s->mb_y == 0 || s->first_slice_line) && block<2) { |
||||
CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
||||
CHECK_MV(P_LAST[0]>>shift, P_LAST[1]>>shift) |
||||
CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) |
||||
}else{ |
||||
CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) |
||||
//FIXME try some early stop
|
||||
if(dmin>64*2){ |
||||
CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) |
||||
CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
||||
CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) |
||||
CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) |
||||
CHECK_MV(P_LAST[0]>>shift, P_LAST[1]>>shift) |
||||
} |
||||
} |
||||
if(dmin>64*4){ |
||||
CHECK_MV(P_LAST_RIGHT[0]>>shift, P_LAST_RIGHT[1]>>shift) |
||||
CHECK_MV(P_LAST_BOTTOM[0]>>shift, P_LAST_BOTTOM[1]>>shift) |
||||
} |
||||
|
||||
if(s->avctx->dia_size<2) |
||||
dmin= RENAME(small_diamond_search)(s, best, dmin, ref_picture, |
||||
pred_x, pred_y, penalty_factor, xmin, ymin, xmax, ymax,
|
||||
shift, map, map_generation, size, mv_penalty); |
||||
else |
||||
dmin= RENAME(var_diamond_search)(s, best, dmin, ref_picture, |
||||
pred_x, pred_y, penalty_factor, xmin, ymin, xmax, ymax,
|
||||
shift, map, map_generation, size, mv_penalty); |
||||
*mx_ptr= best[0]; |
||||
*my_ptr= best[1];
|
||||
|
||||
// printf("%d %d %d \n", best[0], best[1], dmin);
|
||||
return dmin; |
||||
} |
||||
#endif /* !CMP_DIRECT */ |
@ -0,0 +1,850 @@ |
||||
/*
|
||||
* Copyright (c) 2002 The FFmpeg Project. |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU Lesser General Public |
||||
* License as published by the Free Software Foundation; either |
||||
* version 2 of the License, or (at your option) any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
* Lesser General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU Lesser General Public |
||||
* License along with this library; if not, write to the Free Software |
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
* |
||||
*/ |
||||
|
||||
#include "simple_idct.h" |
||||
|
||||
#define SKIP_TYPE_NONE 0 |
||||
#define SKIP_TYPE_MPEG 1 |
||||
#define SKIP_TYPE_ROW 2 |
||||
#define SKIP_TYPE_COL 3 |
||||
|
||||
|
||||
typedef struct Wmv2Context{ |
||||
MpegEncContext s; |
||||
int j_type_bit; |
||||
int j_type; |
||||
int flag3; |
||||
int flag63; |
||||
int abt_flag; |
||||
int abt_type; |
||||
int abt_type_table[6]; |
||||
int per_mb_abt; |
||||
int per_block_abt; |
||||
int mspel_bit; |
||||
int cbp_table_index; |
||||
int top_left_mv_flag; |
||||
int per_mb_rl_bit; |
||||
int skip_type; |
||||
int hshift; |
||||
|
||||
ScanTable abt_scantable[2]; |
||||
DCTELEM abt_block2[6][64] __align8; |
||||
}Wmv2Context; |
||||
|
||||
static void wmv2_common_init(Wmv2Context * w){ |
||||
MpegEncContext * const s= &w->s; |
||||
|
||||
ff_init_scantable(s, &w->abt_scantable[0], wmv2_scantableA); |
||||
ff_init_scantable(s, &w->abt_scantable[1], wmv2_scantableB); |
||||
} |
||||
|
||||
static int encode_ext_header(Wmv2Context *w){ |
||||
MpegEncContext * const s= &w->s; |
||||
PutBitContext pb; |
||||
int code; |
||||
|
||||
init_put_bits(&pb, s->avctx->extradata, s->avctx->extradata_size, NULL, NULL); |
||||
|
||||
put_bits(&pb, 5, s->frame_rate / FRAME_RATE_BASE); //yes 29.97 -> 29
|
||||
put_bits(&pb, 11, FFMIN(s->bit_rate/1024, 2047)); |
||||
|
||||
put_bits(&pb, 1, w->mspel_bit=1); |
||||
put_bits(&pb, 1, w->flag3=1); |
||||
put_bits(&pb, 1, w->abt_flag=1); |
||||
put_bits(&pb, 1, w->j_type_bit=1); |
||||
put_bits(&pb, 1, w->top_left_mv_flag=0); |
||||
put_bits(&pb, 1, w->per_mb_rl_bit=1); |
||||
put_bits(&pb, 3, code=1); |
||||
|
||||
flush_put_bits(&pb); |
||||
|
||||
s->slice_height = s->mb_height / code; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int wmv2_encode_init(AVCodecContext *avctx){ |
||||
Wmv2Context * const w= avctx->priv_data; |
||||
|
||||
if(MPV_encode_init(avctx) < 0) |
||||
return -1; |
||||
|
||||
wmv2_common_init(w); |
||||
|
||||
avctx->extradata_size= 4; |
||||
avctx->extradata= av_mallocz(avctx->extradata_size + 10); |
||||
encode_ext_header(w); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int wmv2_encode_end(AVCodecContext *avctx){ |
||||
Wmv2Context * const w= avctx->priv_data; |
||||
|
||||
if(MPV_encode_end(avctx) < 0) |
||||
return -1; |
||||
|
||||
avctx->extradata_size= 0; |
||||
av_freep(&avctx->extradata); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number) |
||||
{ |
||||
Wmv2Context * const w= (Wmv2Context*)s; |
||||
|
||||
put_bits(&s->pb, 1, s->pict_type - 1); |
||||
if(s->pict_type == I_TYPE){ |
||||
put_bits(&s->pb, 7, 0); |
||||
} |
||||
put_bits(&s->pb, 5, s->qscale); |
||||
|
||||
s->dc_table_index = 1; |
||||
s->mv_table_index = 1; /* only if P frame */ |
||||
// s->use_skip_mb_code = 1; /* only if P frame */
|
||||
s->per_mb_rl_table = 0; |
||||
s->mspel= 0; |
||||
w->per_mb_abt=0; |
||||
w->abt_type=0; |
||||
w->j_type=0; |
||||
|
||||
if (s->pict_type == I_TYPE) { |
||||
if(w->j_type_bit) put_bits(&s->pb, 1, w->j_type); |
||||
|
||||
if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); |
||||
|
||||
if(!s->per_mb_rl_table){ |
||||
code012(&s->pb, s->rl_chroma_table_index); |
||||
code012(&s->pb, s->rl_table_index); |
||||
} |
||||
|
||||
put_bits(&s->pb, 1, s->dc_table_index); |
||||
|
||||
s->inter_intra_pred= 0; |
||||
s->no_rounding = 1; |
||||
}else{ |
||||
int cbp_index; |
||||
|
||||
put_bits(&s->pb, 2, SKIP_TYPE_NONE); |
||||
|
||||
code012(&s->pb, cbp_index=0); |
||||
if(s->qscale <= 10){ |
||||
int map[3]= {0,2,1}; |
||||
w->cbp_table_index= map[cbp_index]; |
||||
}else if(s->qscale <= 20){ |
||||
int map[3]= {1,0,2}; |
||||
w->cbp_table_index= map[cbp_index]; |
||||
}else{ |
||||
int map[3]= {2,1,0}; |
||||
w->cbp_table_index= map[cbp_index]; |
||||
} |
||||
|
||||
if(w->mspel_bit) put_bits(&s->pb, 1, s->mspel); |
||||
|
||||
if(w->abt_flag){ |
||||
put_bits(&s->pb, 1, w->per_mb_abt^1); |
||||
if(!w->per_mb_abt){ |
||||
code012(&s->pb, w->abt_type); |
||||
} |
||||
} |
||||
|
||||
if(w->per_mb_rl_bit) put_bits(&s->pb, 1, s->per_mb_rl_table); |
||||
|
||||
if(!s->per_mb_rl_table){ |
||||
code012(&s->pb, s->rl_table_index); |
||||
s->rl_chroma_table_index = s->rl_table_index; |
||||
} |
||||
put_bits(&s->pb, 1, s->dc_table_index); |
||||
put_bits(&s->pb, 1, s->mv_table_index); |
||||
|
||||
s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); |
||||
s->no_rounding ^= 1; |
||||
} |
||||
s->esc3_level_length= 0; |
||||
s->esc3_run_length= 0; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
// nearly idential to wmv1 but thats just because we dont use the useless M$ crap features
|
||||
// its duplicated here in case someone wants to add support for these carp features
|
||||
void ff_wmv2_encode_mb(MpegEncContext * s,
|
||||
DCTELEM block[6][64], |
||||
int motion_x, int motion_y) |
||||
{ |
||||
Wmv2Context * const w= (Wmv2Context*)s; |
||||
int cbp, coded_cbp, i; |
||||
int pred_x, pred_y; |
||||
UINT8 *coded_block; |
||||
|
||||
handle_slices(s); |
||||
|
||||
if (!s->mb_intra) { |
||||
/* compute cbp */ |
||||
set_stat(ST_INTER_MB); |
||||
cbp = 0; |
||||
for (i = 0; i < 6; i++) { |
||||
if (s->block_last_index[i] >= 0) |
||||
cbp |= 1 << (5 - i); |
||||
} |
||||
|
||||
put_bits(&s->pb,
|
||||
wmv2_inter_table[w->cbp_table_index][cbp + 64][1],
|
||||
wmv2_inter_table[w->cbp_table_index][cbp + 64][0]); |
||||
|
||||
/* motion vector */ |
||||
h263_pred_motion(s, 0, &pred_x, &pred_y); |
||||
msmpeg4_encode_motion(s, motion_x - pred_x,
|
||||
motion_y - pred_y); |
||||
} else { |
||||
/* compute cbp */ |
||||
cbp = 0; |
||||
coded_cbp = 0; |
||||
for (i = 0; i < 6; i++) { |
||||
int val, pred; |
||||
val = (s->block_last_index[i] >= 1); |
||||
cbp |= val << (5 - i); |
||||
if (i < 4) { |
||||
/* predict value for close blocks only for luma */ |
||||
pred = coded_block_pred(s, i, &coded_block); |
||||
*coded_block = val; |
||||
val = val ^ pred; |
||||
} |
||||
coded_cbp |= val << (5 - i); |
||||
} |
||||
#if 0 |
||||
if (coded_cbp) |
||||
printf("cbp=%x %x\n", cbp, coded_cbp); |
||||
#endif |
||||
|
||||
if (s->pict_type == I_TYPE) { |
||||
set_stat(ST_INTRA_MB); |
||||
put_bits(&s->pb,
|
||||
table_mb_intra[coded_cbp][1], table_mb_intra[coded_cbp][0]); |
||||
} else { |
||||
put_bits(&s->pb,
|
||||
wmv2_inter_table[w->cbp_table_index][cbp][1],
|
||||
wmv2_inter_table[w->cbp_table_index][cbp][0]); |
||||
} |
||||
set_stat(ST_INTRA_MB); |
||||
put_bits(&s->pb, 1, 0); /* no AC prediction yet */ |
||||
if(s->inter_intra_pred){ |
||||
s->h263_aic_dir=0; |
||||
put_bits(&s->pb, table_inter_intra[s->h263_aic_dir][1], table_inter_intra[s->h263_aic_dir][0]); |
||||
} |
||||
} |
||||
|
||||
for (i = 0; i < 6; i++) { |
||||
msmpeg4_encode_block(s, block[i], i); |
||||
} |
||||
} |
||||
|
||||
static void parse_mb_skip(Wmv2Context * w){ |
||||
int mb_x, mb_y; |
||||
MpegEncContext * const s= &w->s; |
||||
|
||||
w->skip_type= get_bits(&s->gb, 2); |
||||
switch(w->skip_type){ |
||||
case SKIP_TYPE_NONE: |
||||
for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
||||
for(mb_x=0; mb_x<s->mb_width; mb_x++){ |
||||
s->mb_type[mb_y*s->mb_width + mb_x]= 0; |
||||
} |
||||
} |
||||
break; |
||||
case SKIP_TYPE_MPEG: |
||||
for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
||||
for(mb_x=0; mb_x<s->mb_width; mb_x++){ |
||||
s->mb_type[mb_y*s->mb_width + mb_x]= get_bits1(&s->gb) ? MB_TYPE_SKIPED : 0; |
||||
} |
||||
} |
||||
break; |
||||
case SKIP_TYPE_ROW: |
||||
for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
||||
if(get_bits1(&s->gb)){ |
||||
for(mb_x=0; mb_x<s->mb_width; mb_x++){ |
||||
s->mb_type[mb_y*s->mb_width + mb_x]= MB_TYPE_SKIPED; |
||||
} |
||||
}else{ |
||||
for(mb_x=0; mb_x<s->mb_width; mb_x++){ |
||||
s->mb_type[mb_y*s->mb_width + mb_x]= get_bits1(&s->gb) ? MB_TYPE_SKIPED : 0; |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
case SKIP_TYPE_COL: |
||||
for(mb_x=0; mb_x<s->mb_width; mb_x++){ |
||||
if(get_bits1(&s->gb)){ |
||||
for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
||||
s->mb_type[mb_y*s->mb_width + mb_x]= MB_TYPE_SKIPED; |
||||
} |
||||
}else{ |
||||
for(mb_y=0; mb_y<s->mb_height; mb_y++){ |
||||
s->mb_type[mb_y*s->mb_width + mb_x]= get_bits1(&s->gb) ? MB_TYPE_SKIPED : 0; |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
} |
||||
|
||||
static int decode_ext_header(Wmv2Context *w){ |
||||
MpegEncContext * const s= &w->s; |
||||
GetBitContext gb; |
||||
int fps; |
||||
int code; |
||||
|
||||
if(s->avctx->extradata_size<4) return -1; |
||||
|
||||
init_get_bits(&gb, s->avctx->extradata, s->avctx->extradata_size); |
||||
|
||||
fps = get_bits(&gb, 5); |
||||
s->bit_rate = get_bits(&gb, 11)*1024; |
||||
w->mspel_bit = get_bits1(&gb); |
||||
w->flag3 = get_bits1(&gb); |
||||
w->abt_flag = get_bits1(&gb); |
||||
w->j_type_bit = get_bits1(&gb); |
||||
w->top_left_mv_flag= get_bits1(&gb); |
||||
w->per_mb_rl_bit = get_bits1(&gb); |
||||
code = get_bits(&gb, 3); |
||||
|
||||
if(code==0) return -1; |
||||
|
||||
s->slice_height = s->mb_height / code; |
||||
|
||||
if(s->avctx->debug&FF_DEBUG_PICT_INFO){ |
||||
printf("fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, tl_mv_flag:%d, mbrl_bit:%d, code:%d, flag3:%d\n",
|
||||
fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, w->flag3); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int ff_wmv2_decode_picture_header(MpegEncContext * s) |
||||
{ |
||||
Wmv2Context * const w= (Wmv2Context*)s; |
||||
int code, i; |
||||
|
||||
#if 0 |
||||
{ |
||||
int i; |
||||
for(i=0; i<s->gb.size*8; i++) |
||||
printf("%d", get_bits1(&s->gb)); |
||||
// get_bits1(&s->gb);
|
||||
printf("END\n"); |
||||
return -1; |
||||
} |
||||
#endif |
||||
if(s->picture_number==0) |
||||
decode_ext_header(w); |
||||
|
||||
s->pict_type = get_bits(&s->gb, 1) + 1; |
||||
if(s->pict_type == I_TYPE){ |
||||
code = get_bits(&s->gb, 7); |
||||
printf("I7:%X/\n", code); |
||||
} |
||||
s->qscale = get_bits(&s->gb, 5); |
||||
|
||||
if (s->pict_type == I_TYPE) { |
||||
if(w->j_type_bit) w->j_type= get_bits1(&s->gb); |
||||
else w->j_type= 0; //FIXME check
|
||||
|
||||
if(!w->j_type){ |
||||
if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); |
||||
else s->per_mb_rl_table= 0; |
||||
|
||||
if(!s->per_mb_rl_table){ |
||||
s->rl_chroma_table_index = decode012(&s->gb); |
||||
s->rl_table_index = decode012(&s->gb); |
||||
} |
||||
|
||||
s->dc_table_index = get_bits1(&s->gb); |
||||
} |
||||
s->inter_intra_pred= 0; |
||||
s->no_rounding = 1; |
||||
if(s->avctx->debug&FF_DEBUG_PICT_INFO){ |
||||
printf("qscale:%d rlc:%d rl:%d dc:%d mbrl:%d j_type:%d \n",
|
||||
s->qscale, |
||||
s->rl_chroma_table_index, |
||||
s->rl_table_index,
|
||||
s->dc_table_index, |
||||
s->per_mb_rl_table, |
||||
w->j_type); |
||||
} |
||||
}else{ |
||||
int cbp_index; |
||||
w->j_type=0; |
||||
|
||||
parse_mb_skip(w); |
||||
cbp_index= decode012(&s->gb); |
||||
if(s->qscale <= 10){ |
||||
int map[3]= {0,2,1}; |
||||
w->cbp_table_index= map[cbp_index]; |
||||
}else if(s->qscale <= 20){ |
||||
int map[3]= {1,0,2}; |
||||
w->cbp_table_index= map[cbp_index]; |
||||
}else{ |
||||
int map[3]= {2,1,0}; |
||||
w->cbp_table_index= map[cbp_index]; |
||||
} |
||||
|
||||
if(w->mspel_bit) s->mspel= get_bits1(&s->gb); |
||||
else s->mspel= 0; //FIXME check
|
||||
|
||||
if(w->abt_flag){ |
||||
w->per_mb_abt= get_bits1(&s->gb)^1; |
||||
if(!w->per_mb_abt){ |
||||
w->abt_type= decode012(&s->gb); |
||||
} |
||||
} |
||||
|
||||
if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); |
||||
else s->per_mb_rl_table= 0; |
||||
|
||||
if(!s->per_mb_rl_table){ |
||||
s->rl_table_index = decode012(&s->gb); |
||||
s->rl_chroma_table_index = s->rl_table_index; |
||||
} |
||||
|
||||
s->dc_table_index = get_bits1(&s->gb); |
||||
s->mv_table_index = get_bits1(&s->gb); |
||||
|
||||
s->inter_intra_pred= (s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); |
||||
s->no_rounding ^= 1; |
||||
|
||||
if(s->avctx->debug&FF_DEBUG_PICT_INFO){ |
||||
printf("rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n",
|
||||
s->rl_table_index,
|
||||
s->rl_chroma_table_index,
|
||||
s->dc_table_index, |
||||
s->mv_table_index, |
||||
s->per_mb_rl_table, |
||||
s->qscale, |
||||
s->mspel, |
||||
w->per_mb_abt, |
||||
w->abt_type, |
||||
w->cbp_table_index, |
||||
s->inter_intra_pred); |
||||
} |
||||
} |
||||
s->esc3_level_length= 0; |
||||
s->esc3_run_length= 0; |
||||
|
||||
if(s->avctx->debug&FF_DEBUG_SKIP){ |
||||
for(i=0; i<s->mb_num; i++){ |
||||
if(i%s->mb_width==0) printf("\n"); |
||||
printf("%d", s->mb_type[i]); |
||||
} |
||||
} |
||||
s->picture_number++; //FIXME ?
|
||||
|
||||
|
||||
// if(w->j_type)
|
||||
// return wmv2_decode_j_picture(w); //FIXME
|
||||
|
||||
if(w->j_type){ |
||||
printf("J-type picture isnt supported\n"); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void ff_wmv2_decode_init(MpegEncContext *s){ |
||||
} |
||||
|
||||
static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr){ |
||||
MpegEncContext * const s= &w->s; |
||||
int ret; |
||||
|
||||
ret= msmpeg4_decode_motion(s, mx_ptr, my_ptr); |
||||
|
||||
if(ret<0) return -1; |
||||
|
||||
if((((*mx_ptr)|(*my_ptr)) & 1) && s->mspel) |
||||
w->hshift= get_bits1(&s->gb); |
||||
else
|
||||
w->hshift= 0; |
||||
|
||||
//printf("%d %d ", *mx_ptr, *my_ptr);
|
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ |
||||
MpegEncContext * const s= &w->s; |
||||
int xy, wrap, diff, type; |
||||
INT16 *A, *B, *C, *mot_val; |
||||
|
||||
wrap = s->block_wrap[0]; |
||||
xy = s->block_index[0]; |
||||
|
||||
mot_val = s->motion_val[xy]; |
||||
|
||||
A = s->motion_val[xy - 1]; |
||||
B = s->motion_val[xy - wrap]; |
||||
C = s->motion_val[xy + 2 - wrap]; |
||||
|
||||
diff= FFMAX(ABS(A[0] - B[0]), ABS(A[1] - B[1])); |
||||
|
||||
if(s->mb_x && s->mb_y && !s->mspel && w->top_left_mv_flag && diff >= 8) |
||||
//FIXME top/left bit too if y=!0 && first_slice_line?
|
||||
type= get_bits1(&s->gb); |
||||
else |
||||
type= 2; |
||||
|
||||
if(type == 0){ |
||||
*px= A[0]; |
||||
*py= A[1]; |
||||
}else if(type == 1){ |
||||
*px= B[0]; |
||||
*py= B[1]; |
||||
}else{ |
||||
/* special case for first (slice) line */ |
||||
if (s->first_slice_line) { |
||||
*px = A[0]; |
||||
*py = A[1]; |
||||
} else { |
||||
*px = mid_pred(A[0], B[0], C[0]); |
||||
*py = mid_pred(A[1], B[1], C[1]); |
||||
} |
||||
} |
||||
|
||||
return mot_val; |
||||
} |
||||
|
||||
static inline int wmv2_decode_inter_block(Wmv2Context *w, DCTELEM *block, int n, int cbp){ |
||||
MpegEncContext * const s= &w->s; |
||||
static const int sub_cbp_table[3]= {2,3,1}; |
||||
int sub_cbp; |
||||
|
||||
if(!cbp){
|
||||
s->block_last_index[n] = -1; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
if(w->per_block_abt) |
||||
w->abt_type= decode012(&s->gb); |
||||
#if 0 |
||||
if(w->per_block_abt) |
||||
printf("B%d", w->abt_type); |
||||
#endif |
||||
w->abt_type_table[n]= w->abt_type; |
||||
|
||||
if(w->abt_type){ |
||||
// const uint8_t *scantable= w->abt_scantable[w->abt_type-1].permutated;
|
||||
const uint8_t *scantable= w->abt_scantable[w->abt_type-1].scantable; |
||||
// const uint8_t *scantable= w->abt_type-1 ? w->abt_scantable[1].permutated : w->abt_scantable[0].scantable;
|
||||
|
||||
sub_cbp= sub_cbp_table[ decode012(&s->gb) ]; |
||||
// printf("S%d", sub_cbp);
|
||||
|
||||
if(sub_cbp&1){ |
||||
if (msmpeg4_decode_block(s, block, n, 1, scantable) < 0) |
||||
return -1; |
||||
} |
||||
|
||||
if(sub_cbp&2){ |
||||
if (msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0) |
||||
return -1; |
||||
} |
||||
s->block_last_index[n] = 63; |
||||
|
||||
return 0; |
||||
}else{ |
||||
return msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated); |
||||
} |
||||
} |
||||
|
||||
static void wmv2_add_block(Wmv2Context *w, DCTELEM *block1, uint8_t *dst, int stride, int n){ |
||||
MpegEncContext * const s= &w->s; |
||||
uint8_t temp[2][64]; |
||||
int i; |
||||
|
||||
if(w->abt_type_table[n] && 0){ |
||||
int a,b; |
||||
|
||||
a= block1[0]; |
||||
b= w->abt_block2[n][0]; |
||||
block1[0]= a+b; |
||||
w->abt_block2[n][0]= a-b; |
||||
} |
||||
|
||||
switch(w->abt_type_table[n]){ |
||||
case 0: |
||||
if (s->block_last_index[n] >= 0) { |
||||
s->idct_add (dst, stride, block1); |
||||
} |
||||
break; |
||||
case 1: |
||||
simple_idct84_add(dst , stride, block1); |
||||
simple_idct84_add(dst + 4*stride, stride, w->abt_block2[n]); |
||||
memset(w->abt_block2[n], 0, 64*sizeof(DCTELEM)); |
||||
break; |
||||
case 2: |
||||
simple_idct48_add(dst , stride, block1); |
||||
simple_idct48_add(dst + 4 , stride, w->abt_block2[n]); |
||||
memset(w->abt_block2[n], 0, 64*sizeof(DCTELEM)); |
||||
break; |
||||
default: |
||||
fprintf(stderr, "internal error in WMV2 abt\n"); |
||||
} |
||||
} |
||||
|
||||
void ff_wmv2_add_mb(MpegEncContext *s, DCTELEM block1[6][64], uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr){ |
||||
Wmv2Context * const w= (Wmv2Context*)s; |
||||
|
||||
wmv2_add_block(w, block1[0], dest_y , s->linesize, 0); |
||||
wmv2_add_block(w, block1[1], dest_y + 8 , s->linesize, 1); |
||||
wmv2_add_block(w, block1[2], dest_y + 8*s->linesize, s->linesize, 2); |
||||
wmv2_add_block(w, block1[3], dest_y + 8 + 8*s->linesize, s->linesize, 3); |
||||
|
||||
if(s->flags&CODEC_FLAG_GRAY) return; |
||||
|
||||
wmv2_add_block(w, block1[4], dest_cb , s->uvlinesize, 4); |
||||
wmv2_add_block(w, block1[5], dest_cr , s->uvlinesize, 5); |
||||
} |
||||
|
||||
void ff_mspel_motion(MpegEncContext *s, |
||||
UINT8 *dest_y, UINT8 *dest_cb, UINT8 *dest_cr, |
||||
UINT8 **ref_picture, op_pixels_func (*pix_op)[4], |
||||
int motion_x, int motion_y, int h) |
||||
{ |
||||
Wmv2Context * const w= (Wmv2Context*)s; |
||||
UINT8 *ptr; |
||||
int dxy, offset, mx, my, src_x, src_y, v_edge_pos, linesize, uvlinesize; |
||||
int emu=0; |
||||
|
||||
dxy = ((motion_y & 1) << 1) | (motion_x & 1); |
||||
dxy = 2*dxy + w->hshift; |
||||
src_x = s->mb_x * 16 + (motion_x >> 1); |
||||
src_y = s->mb_y * 16 + (motion_y >> 1); |
||||
|
||||
/* WARNING: do no forget half pels */ |
||||
v_edge_pos = s->v_edge_pos; |
||||
src_x = clip(src_x, -16, s->width); |
||||
src_y = clip(src_y, -16, s->height); |
||||
linesize = s->linesize; |
||||
uvlinesize = s->uvlinesize; |
||||
ptr = ref_picture[0] + (src_y * linesize) + src_x; |
||||
|
||||
if(s->flags&CODEC_FLAG_EMU_EDGE){ |
||||
if(src_x<1 || src_y<1 || src_x + 17 >= s->h_edge_pos |
||||
|| src_y + h+1 >= v_edge_pos){ |
||||
ff_emulated_edge_mc(s, ptr - 1 - s->linesize, s->linesize, 19, 19,
|
||||
src_x-1, src_y-1, s->h_edge_pos, s->v_edge_pos); |
||||
ptr= s->edge_emu_buffer + 1 + s->linesize; |
||||
emu=1; |
||||
} |
||||
} |
||||
|
||||
s->dsp.put_mspel_pixels_tab[dxy](dest_y , ptr , linesize); |
||||
s->dsp.put_mspel_pixels_tab[dxy](dest_y+8 , ptr+8 , linesize); |
||||
s->dsp.put_mspel_pixels_tab[dxy](dest_y +8*linesize, ptr +8*linesize, linesize); |
||||
s->dsp.put_mspel_pixels_tab[dxy](dest_y+8+8*linesize, ptr+8+8*linesize, linesize); |
||||
|
||||
if(s->flags&CODEC_FLAG_GRAY) return; |
||||
|
||||
if (s->out_format == FMT_H263) { |
||||
dxy = 0; |
||||
if ((motion_x & 3) != 0) |
||||
dxy |= 1; |
||||
if ((motion_y & 3) != 0) |
||||
dxy |= 2; |
||||
mx = motion_x >> 2; |
||||
my = motion_y >> 2; |
||||
} else { |
||||
mx = motion_x / 2; |
||||
my = motion_y / 2; |
||||
dxy = ((my & 1) << 1) | (mx & 1); |
||||
mx >>= 1; |
||||
my >>= 1; |
||||
} |
||||
|
||||
src_x = s->mb_x * 8 + mx; |
||||
src_y = s->mb_y * 8 + my; |
||||
src_x = clip(src_x, -8, s->width >> 1); |
||||
if (src_x == (s->width >> 1)) |
||||
dxy &= ~1; |
||||
src_y = clip(src_y, -8, s->height >> 1); |
||||
if (src_y == (s->height >> 1)) |
||||
dxy &= ~2; |
||||
offset = (src_y * uvlinesize) + src_x; |
||||
ptr = ref_picture[1] + offset; |
||||
if(emu){ |
||||
ff_emulated_edge_mc(s, ptr, s->uvlinesize, 9, 9,
|
||||
src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); |
||||
ptr= s->edge_emu_buffer; |
||||
} |
||||
pix_op[1][dxy](dest_cb, ptr, uvlinesize, h >> 1); |
||||
|
||||
ptr = ref_picture[2] + offset; |
||||
if(emu){ |
||||
ff_emulated_edge_mc(s, ptr, s->uvlinesize, 9, 9,
|
||||
src_x, src_y, s->h_edge_pos>>1, s->v_edge_pos>>1); |
||||
ptr= s->edge_emu_buffer; |
||||
} |
||||
pix_op[1][dxy](dest_cr, ptr, uvlinesize, h >> 1); |
||||
} |
||||
|
||||
|
||||
static int wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) |
||||
{ |
||||
Wmv2Context * const w= (Wmv2Context*)s; |
||||
int cbp, code, i; |
||||
UINT8 *coded_val; |
||||
|
||||
if(w->j_type) return 0; |
||||
|
||||
s->error_status_table[s->mb_x + s->mb_y*s->mb_width]= 0; |
||||
|
||||
if (s->pict_type == P_TYPE) { |
||||
if(s->mb_type[s->mb_y * s->mb_width + s->mb_x]&MB_TYPE_SKIPED){ |
||||
/* skip mb */ |
||||
s->mb_intra = 0; |
||||
for(i=0;i<6;i++) |
||||
s->block_last_index[i] = -1; |
||||
s->mv_dir = MV_DIR_FORWARD; |
||||
s->mv_type = MV_TYPE_16X16; |
||||
s->mv[0][0][0] = 0; |
||||
s->mv[0][0][1] = 0; |
||||
s->mb_skiped = 1; |
||||
return 0; |
||||
} |
||||
|
||||
code = get_vlc2(&s->gb, mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); |
||||
if (code < 0) |
||||
return -1; |
||||
s->mb_intra = (~code & 0x40) >> 6; |
||||
|
||||
cbp = code & 0x3f; |
||||
} else { |
||||
s->mb_intra = 1; |
||||
code = get_vlc2(&s->gb, mb_intra_vlc.table, MB_INTRA_VLC_BITS, 2); |
||||
if (code < 0){ |
||||
fprintf(stderr, "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); |
||||
return -1; |
||||
} |
||||
/* predict coded block pattern */ |
||||
cbp = 0; |
||||
for(i=0;i<6;i++) { |
||||
int val = ((code >> (5 - i)) & 1); |
||||
if (i < 4) { |
||||
int pred = coded_block_pred(s, i, &coded_val); |
||||
val = val ^ pred; |
||||
*coded_val = val; |
||||
} |
||||
cbp |= val << (5 - i); |
||||
} |
||||
} |
||||
|
||||
if (!s->mb_intra) { |
||||
int mx, my; |
||||
//printf("P at %d %d\n", s->mb_x, s->mb_y);
|
||||
wmv2_pred_motion(w, &mx, &my); |
||||
|
||||
if(cbp){ |
||||
if(s->per_mb_rl_table){ |
||||
s->rl_table_index = decode012(&s->gb); |
||||
s->rl_chroma_table_index = s->rl_table_index; |
||||
} |
||||
|
||||
if(w->abt_flag && w->per_mb_abt){ |
||||
w->per_block_abt= get_bits1(&s->gb); |
||||
if(!w->per_block_abt) |
||||
w->abt_type= decode012(&s->gb); |
||||
}else |
||||
w->per_block_abt=0; |
||||
} |
||||
|
||||
if (wmv2_decode_motion(w, &mx, &my) < 0) |
||||
return -1; |
||||
|
||||
s->mv_dir = MV_DIR_FORWARD; |
||||
s->mv_type = MV_TYPE_16X16; |
||||
s->mv[0][0][0] = mx; |
||||
s->mv[0][0][1] = my; |
||||
|
||||
for (i = 0; i < 6; i++) { |
||||
if (wmv2_decode_inter_block(w, block[i], i, (cbp >> (5 - i)) & 1) < 0) |
||||
{ |
||||
fprintf(stderr,"\nerror while decoding inter block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); |
||||
return -1; |
||||
} |
||||
}
|
||||
} else { |
||||
//if(s->pict_type==P_TYPE)
|
||||
// printf("%d%d ", s->inter_intra_pred, cbp);
|
||||
//printf("I at %d %d %d %06X\n", s->mb_x, s->mb_y, ((cbp&3)? 1 : 0) +((cbp&0x3C)? 2 : 0), show_bits(&s->gb, 24));
|
||||
s->ac_pred = get_bits1(&s->gb); |
||||
if(s->inter_intra_pred){ |
||||
s->h263_aic_dir= get_vlc2(&s->gb, inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); |
||||
// printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y);
|
||||
} |
||||
if(s->per_mb_rl_table && cbp){ |
||||
s->rl_table_index = decode012(&s->gb); |
||||
s->rl_chroma_table_index = s->rl_table_index; |
||||
} |
||||
|
||||
for (i = 0; i < 6; i++) { |
||||
if (msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) |
||||
{ |
||||
fprintf(stderr,"\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); |
||||
return -1; |
||||
} |
||||
}
|
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int wmv2_decode_init(AVCodecContext *avctx){ |
||||
Wmv2Context * const w= avctx->priv_data; |
||||
|
||||
if(ff_h263_decode_init(avctx) < 0) |
||||
return -1; |
||||
|
||||
wmv2_common_init(w); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
AVCodec wmv2_decoder = { |
||||
"wmv2", |
||||
CODEC_TYPE_VIDEO, |
||||
CODEC_ID_WMV2, |
||||
sizeof(Wmv2Context), |
||||
wmv2_decode_init, |
||||
NULL, |
||||
ff_h263_decode_end, |
||||
ff_h263_decode_frame, |
||||
CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, |
||||
}; |
||||
|
||||
AVCodec wmv2_encoder = { |
||||
"wmv2", |
||||
CODEC_TYPE_VIDEO, |
||||
CODEC_ID_WMV2, |
||||
sizeof(Wmv2Context), |
||||
wmv2_encode_init, |
||||
MPV_encode_picture, |
||||
MPV_encode_end, |
||||
}; |
||||
|
Loading…
Reference in new issue