annotate libavcodec/h264_mc.c @ 9:ea1ba68cf0ed

update to match api changes + add sscc produced source
author Nina Engelhardt <nengel@mailbox.tu-berlin.de>
date Wed, 05 Jun 2013 14:43:26 +0200
parents
children
rev   line source
nengel@2 1 #include "h264_types.h"
nengel@2 2 #include "h264_data.h"
nengel@2 3
nengel@2 4 static inline void mc_dir_part(MBRecContext *d, MBRecState *mrs, H264Mb *m, DecodedPicture *pic, int n, int square,
nengel@2 5 int chroma_height, int delta, int list,uint8_t *dest_y,
nengel@2 6 uint8_t *dest_cb, uint8_t *dest_cr, int src_x_offset, int src_y_offset,
nengel@2 7 qpel_mc_func *qpix_op, h264_chroma_mc_func chroma_op){
nengel@2 8 const int mx= mrs->mv_cache[list][ scan8[n] ][0] + src_x_offset*8;
nengel@2 9 const int my= mrs->mv_cache[list][ scan8[n] ][1] + src_y_offset*8;
nengel@2 10 const int luma_xy= (mx&3) + ((my&3)<<2);
nengel@2 11 const int pic_width = 16*d->mb_width;
nengel@2 12 const int pic_height = 16*d->mb_height;
nengel@2 13
nengel@2 14 uint8_t *src_y, *src_cb, *src_cr;
nengel@2 15 int ymx= mx>>2;
nengel@2 16 int ymy= my>>2;
nengel@2 17 int cmy= my>>3;
nengel@2 18 int cmx= mx>>3;
nengel@2 19
nengel@2 20 //truncate the motion vectors references
nengel@2 21 if(ymy>= pic_height+2){
nengel@2 22 ymy=pic_height+1;
nengel@2 23 }else if(ymy <=-19){
nengel@2 24 ymy=-18;
nengel@2 25 }
nengel@2 26 if(ymx>= pic_width+2){
nengel@2 27 ymx= pic_width+1;
nengel@2 28 }else if(ymx<=-19){
nengel@2 29 ymx=-19;
nengel@2 30 }
nengel@2 31
nengel@2 32 src_y = pic->data[0] + ymx + ymy*d->linesize;
nengel@2 33 qpix_op[luma_xy](dest_y, src_y, d->linesize); //FIXME try variable height perhaps?
nengel@2 34 if(!square){
nengel@2 35 qpix_op[luma_xy](dest_y + delta, src_y + delta, d->linesize);
nengel@2 36 }
nengel@2 37
nengel@2 38 if(cmy >= pic_height>>1){
nengel@2 39 cmy = (pic_height>>1) -1;
nengel@2 40 }else if(cmy<=-9){
nengel@2 41 cmy=-8;
nengel@2 42 }
nengel@2 43 if(cmx >= pic_width>>1){
nengel@2 44 cmx = (pic_width>>1) -1;
nengel@2 45 }else if(cmx<=-9){
nengel@2 46 cmx=-8;
nengel@2 47 }
nengel@2 48
nengel@2 49 src_cb= pic->data[1] + cmx + cmy*d->uvlinesize;
nengel@2 50 src_cr= pic->data[2] + cmx + cmy*d->uvlinesize;
nengel@2 51
nengel@2 52 chroma_op(dest_cb, src_cb, d->uvlinesize, chroma_height, mx&7, my&7);
nengel@2 53 chroma_op(dest_cr, src_cr, d->uvlinesize, chroma_height, mx&7, my&7);
nengel@2 54 }
nengel@2 55
nengel@2 56 static inline void mc_part_std(MBRecContext *d, MBRecState *mrs, H264Slice *s, H264Mb *m, int n, int square, int chroma_height, int delta,
nengel@2 57 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
nengel@2 58 int x_offset, int y_offset,
nengel@2 59 qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
nengel@2 60 qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg,
nengel@2 61 int list0, int list1){
nengel@2 62 qpel_mc_func *qpix_op= qpix_put;
nengel@2 63 h264_chroma_mc_func chroma_op= chroma_put;
nengel@2 64
nengel@2 65 dest_y += 2*x_offset + 2*y_offset*d-> linesize;
nengel@2 66 dest_cb += x_offset + y_offset*d->uvlinesize;
nengel@2 67 dest_cr += x_offset + y_offset*d->uvlinesize;
nengel@2 68 x_offset += 8*m->mb_x;
nengel@2 69 y_offset += 8*m->mb_y;
nengel@2 70
nengel@2 71 if(list0){
nengel@2 72 DecodedPicture *ref= s->dp_ref_list[0][ mrs->ref_cache[0][ scan8[n] ] ];
nengel@2 73 mc_dir_part(d, mrs, m, ref, n, square, chroma_height, delta, 0,
nengel@2 74 dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_op, chroma_op);
nengel@2 75
nengel@2 76 qpix_op= qpix_avg;
nengel@2 77 chroma_op= chroma_avg;
nengel@2 78 }
nengel@2 79
nengel@2 80 if(list1){
nengel@2 81 DecodedPicture *ref= s->dp_ref_list[1][ mrs->ref_cache[1][ scan8[n] ] ];
nengel@2 82 mc_dir_part(d, mrs, m, ref, n, square, chroma_height, delta, 1,
nengel@2 83 dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_op, chroma_op);
nengel@2 84 }
nengel@2 85 }
nengel@2 86
nengel@2 87 static inline void mc_part_weighted(MBRecContext *d, MBRecState *mrs, H264Slice *s, H264Mb *m, int n, int square, int chroma_height, int delta,
nengel@2 88 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
nengel@2 89 int x_offset, int y_offset,
nengel@2 90 qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
nengel@2 91 h264_weight_func luma_weight_op, h264_weight_func chroma_weight_op,
nengel@2 92 h264_biweight_func luma_weight_avg, h264_biweight_func chroma_weight_avg,
nengel@2 93 int list0, int list1){
nengel@2 94 dest_y += 2*x_offset + 2*y_offset*d-> linesize;
nengel@2 95 dest_cb += x_offset + y_offset*d->uvlinesize;
nengel@2 96 dest_cr += x_offset + y_offset*d->uvlinesize;
nengel@2 97 x_offset += 8*m->mb_x;
nengel@2 98 y_offset += 8*m->mb_y;
nengel@2 99
nengel@2 100 if(list0 && list1){
nengel@2 101 /* don't optimize for luma-only case, since B-frames usually
nengel@2 102 * use implicit weights => chroma too. */
nengel@2 103 uint8_t *tmp_y = d->scratchpad_y + 2*x_offset +16 ;
nengel@2 104 uint8_t *tmp_cb = d->scratchpad_cb + x_offset + 8;
nengel@2 105 uint8_t *tmp_cr = d->scratchpad_cr + x_offset + 8;
nengel@2 106
nengel@2 107 /*
nengel@2 108 uint8_t *tmp_cb = d->scratchpad;
nengel@2 109 uint8_t *tmp_cr = d->scratchpad + 8;
nengel@2 110 uint8_t *tmp_y = d->scratchpad + 8*d->uvlinesize;*/
nengel@2 111 int refn0 = mrs->ref_cache[0][ scan8[n] ];
nengel@2 112 int refn1 = mrs->ref_cache[1][ scan8[n] ];
nengel@2 113
nengel@2 114 mc_dir_part(d, mrs, m, s->dp_ref_list[0][refn0], n, square, chroma_height, delta, 0,
nengel@2 115 dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put, chroma_put);
nengel@2 116 mc_dir_part(d, mrs, m, s->dp_ref_list[1][refn1], n, square, chroma_height, delta, 1,
nengel@2 117 tmp_y, tmp_cb, tmp_cr, x_offset, y_offset, qpix_put, chroma_put);
nengel@2 118
nengel@2 119 if(s->use_weight == 2){
nengel@2 120 int weight0 = s->implicit_weight[refn0][refn1][m->mb_y&1];
nengel@2 121 int weight1 = 64 - weight0;
nengel@2 122 luma_weight_avg( dest_y, tmp_y, d-> linesize, 5, weight0, weight1, 0);
nengel@2 123 chroma_weight_avg(dest_cb, tmp_cb, d->uvlinesize, 5, weight0, weight1, 0);
nengel@2 124 chroma_weight_avg(dest_cr, tmp_cr, d->uvlinesize, 5, weight0, weight1, 0);
nengel@2 125 }else{
nengel@2 126 luma_weight_avg(dest_y, tmp_y, d->linesize, s->luma_log2_weight_denom,
nengel@2 127 s->luma_weight[refn0][0][0] , s->luma_weight[refn1][1][0],
nengel@2 128 s->luma_weight[refn0][0][1] + s->luma_weight[refn1][1][1]);
nengel@2 129 chroma_weight_avg(dest_cb, tmp_cb, d->uvlinesize, s->chroma_log2_weight_denom,
nengel@2 130 s->chroma_weight[refn0][0][0][0] , s->chroma_weight[refn1][1][0][0],
nengel@2 131 s->chroma_weight[refn0][0][0][1] + s->chroma_weight[refn1][1][0][1]);
nengel@2 132 chroma_weight_avg(dest_cr, tmp_cr, d->uvlinesize, s->chroma_log2_weight_denom,
nengel@2 133 s->chroma_weight[refn0][0][1][0] , s->chroma_weight[refn1][1][1][0],
nengel@2 134 s->chroma_weight[refn0][0][1][1] + s->chroma_weight[refn1][1][1][1]);
nengel@2 135 }
nengel@2 136 }else{
nengel@2 137 int list = list1 ? 1 : 0;
nengel@2 138 int refn = mrs->ref_cache[list][ scan8[n] ];
nengel@2 139 DecodedPicture *ref= s->dp_ref_list[list][refn];
nengel@2 140 mc_dir_part(d, mrs, m, ref, n, square, chroma_height, delta, list,
nengel@2 141 dest_y, dest_cb, dest_cr, x_offset, y_offset, qpix_put, chroma_put);
nengel@2 142
nengel@2 143 luma_weight_op(dest_y, d->linesize, s->luma_log2_weight_denom,
nengel@2 144 s->luma_weight[refn][list][0], s->luma_weight[refn][list][1]);
nengel@2 145 if(s->use_weight_chroma){
nengel@2 146 chroma_weight_op(dest_cb, d->uvlinesize, s->chroma_log2_weight_denom,
nengel@2 147 s->chroma_weight[refn][list][0][0], s->chroma_weight[refn][list][0][1]);
nengel@2 148 chroma_weight_op(dest_cr, d->uvlinesize, s->chroma_log2_weight_denom,
nengel@2 149 s->chroma_weight[refn][list][1][0], s->chroma_weight[refn][list][1][1]);
nengel@2 150 }
nengel@2 151 }
nengel@2 152 }
nengel@2 153
nengel@2 154 static inline void mc_part(MBRecContext *d, MBRecState *mrs, H264Slice *s, H264Mb *m, int n, int square, int chroma_height, int delta,
nengel@2 155 uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
nengel@2 156 int x_offset, int y_offset,
nengel@2 157 qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
nengel@2 158 qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg,
nengel@2 159 h264_weight_func *weight_op, h264_biweight_func *weight_avg,
nengel@2 160 int list0, int list1){
nengel@2 161 if((s->use_weight==2 && list0 && list1
nengel@2 162 && (s->implicit_weight[ mrs->ref_cache[0][scan8[n]] ][ mrs->ref_cache[1][scan8[n]] ][m->mb_y&1] != 32))
nengel@2 163 || s->use_weight==1)
nengel@2 164 mc_part_weighted(d, mrs, s, m, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
nengel@2 165 x_offset, y_offset, qpix_put, chroma_put,
nengel@2 166 weight_op[0], weight_op[3], weight_avg[0], weight_avg[3], list0, list1);
nengel@2 167 else
nengel@2 168 mc_part_std(d, mrs, s, m, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
nengel@2 169 x_offset, y_offset, qpix_put, chroma_put, qpix_avg, chroma_avg, list0, list1);
nengel@2 170 }
nengel@2 171
nengel@2 172 static inline void prefetch_motion(MBRecContext *d, MBRecState *mrs, H264Slice *s, H264Mb *m, int list){
nengel@2 173 /* fetch pixels for estimated mv 4 macroblocks ahead
nengel@2 174 * optimized for 64byte cache lines */
nengel@2 175 const int refn = mrs->ref_cache[list][scan8[0]];
nengel@2 176
nengel@2 177 if(refn >= 0){
nengel@2 178 const int mx= (mrs->mv_cache[list][scan8[0]][0]>>2) + 16*m->mb_x + 8;
nengel@2 179 const int my= (mrs->mv_cache[list][scan8[0]][1]>>2) + 16*m->mb_y;
nengel@2 180 uint8_t **src= s->dp_ref_list[list][refn]->data;
nengel@2 181 int off= mx + (my + (m->mb_x&3)*4)*d->linesize + 64;
nengel@2 182
nengel@2 183 d->dsp.prefetch(src[0]+off, d->linesize, 4);
nengel@2 184 off= (mx>>1) + ((my>>1) + (m->mb_x&7))*d->uvlinesize + 64;
nengel@2 185 d->dsp.prefetch(src[1]+off, src[2]-src[1], 2);
nengel@2 186 }
nengel@2 187 }
nengel@2 188
nengel@2 189 void hl_motion(MBRecContext *d, MBRecState *mrs, H264Slice *s, H264Mb *m, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
nengel@2 190 qpel_mc_func (*qpix_put)[16], h264_chroma_mc_func (*chroma_put),
nengel@2 191 qpel_mc_func (*qpix_avg)[16], h264_chroma_mc_func (*chroma_avg),
nengel@2 192 h264_weight_func *weight_op, h264_biweight_func *weight_avg){
nengel@2 193 const int mb_type= m->mb_type;
nengel@2 194 assert(IS_INTER(mb_type));
nengel@2 195
nengel@2 196 if (mb_type & MB_TYPE_L0)
nengel@2 197 prefetch_motion(d, mrs, s, m, 0);
nengel@2 198 if (mb_type & MB_TYPE_L1)
nengel@2 199 prefetch_motion(d, mrs, s, m, 1);
nengel@2 200
nengel@2 201 if(IS_16X16(mb_type)){
nengel@2 202 mc_part(d, mrs, s, m, 0, 1, 8, 0, dest_y, dest_cb, dest_cr, 0, 0,
nengel@2 203 qpix_put[0], chroma_put[0], qpix_avg[0], chroma_avg[0],
nengel@2 204 weight_op, weight_avg,
nengel@2 205 IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
nengel@2 206 }else if(IS_16X8(mb_type)){
nengel@2 207 mc_part(d, mrs, s, m, 0, 0, 4, 8, dest_y, dest_cb, dest_cr, 0, 0,
nengel@2 208 qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
nengel@2 209 &weight_op[1], &weight_avg[1],
nengel@2 210 IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
nengel@2 211 mc_part(d, mrs, s, m, 8, 0, 4, 8, dest_y, dest_cb, dest_cr, 0, 4,
nengel@2 212 qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
nengel@2 213 &weight_op[1], &weight_avg[1],
nengel@2 214 IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1));
nengel@2 215 }else if(IS_8X16(mb_type)){
nengel@2 216 mc_part(d, mrs, s, m, 0, 0, 8, 8*d->linesize, dest_y, dest_cb, dest_cr, 0, 0,
nengel@2 217 qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
nengel@2 218 &weight_op[2], &weight_avg[2],
nengel@2 219 IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
nengel@2 220 mc_part(d, mrs, s, m, 4, 0, 8, 8*d->linesize, dest_y, dest_cb, dest_cr, 4, 0,
nengel@2 221 qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
nengel@2 222 &weight_op[2], &weight_avg[2],
nengel@2 223 IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1));
nengel@2 224 }else{
nengel@2 225 int i;
nengel@2 226
nengel@2 227 assert(IS_8X8(mb_type));
nengel@2 228
nengel@2 229 for(i=0; i<4; i++){
nengel@2 230 const int sub_mb_type= m->sub_mb_type[i];
nengel@2 231 const int n= 4*i;
nengel@2 232 int x_offset= (i&1)<<2;
nengel@2 233 int y_offset= (i&2)<<1;
nengel@2 234
nengel@2 235 if(IS_SUB_8X8(sub_mb_type)){
nengel@2 236 mc_part(d, mrs, s, m, n, 1, 4, 0, dest_y, dest_cb, dest_cr, x_offset, y_offset,
nengel@2 237 qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
nengel@2 238 &weight_op[3], &weight_avg[3],
nengel@2 239 IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
nengel@2 240 }else if(IS_SUB_8X4(sub_mb_type)){
nengel@2 241 mc_part(d, mrs, s, m, n, 0, 2, 4, dest_y, dest_cb, dest_cr, x_offset, y_offset,
nengel@2 242 qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
nengel@2 243 &weight_op[4], &weight_avg[4],
nengel@2 244 IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
nengel@2 245 mc_part(d, mrs, s, m, n+2, 0, 2, 4, dest_y, dest_cb, dest_cr, x_offset, y_offset+2,
nengel@2 246 qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
nengel@2 247 &weight_op[4], &weight_avg[4],
nengel@2 248 IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
nengel@2 249 }else if(IS_SUB_4X8(sub_mb_type)){
nengel@2 250 mc_part(d, mrs, s, m, n, 0, 4, 4*d->linesize, dest_y, dest_cb, dest_cr, x_offset, y_offset,
nengel@2 251 qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
nengel@2 252 &weight_op[5], &weight_avg[5],
nengel@2 253 IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
nengel@2 254 mc_part(d, mrs, s, m, n+1, 0, 4, 4*d->linesize, dest_y, dest_cb, dest_cr, x_offset+2, y_offset,
nengel@2 255 qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
nengel@2 256 &weight_op[5], &weight_avg[5],
nengel@2 257 IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
nengel@2 258 }else{
nengel@2 259 int j;
nengel@2 260 assert(IS_SUB_4X4(sub_mb_type));
nengel@2 261 for(j=0; j<4; j++){
nengel@2 262 int sub_x_offset= x_offset + 2*(j&1);
nengel@2 263 int sub_y_offset= y_offset + (j&2);
nengel@2 264 mc_part(d, mrs, s, m, n+j, 1, 2, 0, dest_y, dest_cb, dest_cr, sub_x_offset, sub_y_offset,
nengel@2 265 qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
nengel@2 266 &weight_op[6], &weight_avg[6],
nengel@2 267 IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
nengel@2 268 }
nengel@2 269 }
nengel@2 270 }
nengel@2 271 }
nengel@2 272 }