]> git.sesse.net Git - ffmpeg/blob - libavcodec/h264_hl_motion.h
Merge remote branch 'qatar/master'
[ffmpeg] / libavcodec / h264_hl_motion.h
1
2 static inline void FUNC(mc_dir_part)(H264Context *h, Picture *pic, int n, int square, int chroma_height, int delta, int list,
3                            uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
4                            int src_x_offset, int src_y_offset,
5                            qpel_mc_func *qpix_op, h264_chroma_mc_func chroma_op){
6     MpegEncContext * const s = &h->s;
7     const int mx= h->mv_cache[list][ scan8[n] ][0] + src_x_offset*8;
8     int my=       h->mv_cache[list][ scan8[n] ][1] + src_y_offset*8;
9     const int luma_xy= (mx&3) + ((my&3)<<2);
10     uint8_t * src_y = pic->data[0] + ((mx>>2)<<PIXEL_SHIFT) + (my>>2)*h->mb_linesize;
11     uint8_t * src_cb, * src_cr;
12     int extra_width= h->emu_edge_width;
13     int extra_height= h->emu_edge_height;
14     int emu=0;
15     const int full_mx= mx>>2;
16     const int full_my= my>>2;
17     const int pic_width  = 16*s->mb_width;
18     const int pic_height = 16*s->mb_height >> MB_FIELD;
19
20     if(mx&7) extra_width -= 3;
21     if(my&7) extra_height -= 3;
22
23     if(   full_mx < 0-extra_width
24        || full_my < 0-extra_height
25        || full_mx + 16/*FIXME*/ > pic_width + extra_width
26        || full_my + 16/*FIXME*/ > pic_height + extra_height){
27         s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_y - (2<<PIXEL_SHIFT) - 2*h->mb_linesize, h->mb_linesize, 16+5, 16+5/*FIXME*/, full_mx-2, full_my-2, pic_width, pic_height);
28             src_y= s->edge_emu_buffer + (2<<PIXEL_SHIFT) + 2*h->mb_linesize;
29         emu=1;
30     }
31
32     qpix_op[luma_xy](dest_y, src_y, h->mb_linesize); //FIXME try variable height perhaps?
33     if(!square){
34         qpix_op[luma_xy](dest_y + delta, src_y + delta, h->mb_linesize);
35     }
36
37     if(CONFIG_GRAY && s->flags&CODEC_FLAG_GRAY) return;
38
39     if(MB_FIELD){
40         // chroma offset when predicting from a field of opposite parity
41         my += 2 * ((s->mb_y & 1) - (pic->reference - 1));
42         emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1);
43     }
44     src_cb= pic->data[1] + ((mx>>3)<<PIXEL_SHIFT) + (my>>3)*h->mb_uvlinesize;
45     src_cr= pic->data[2] + ((mx>>3)<<PIXEL_SHIFT) + (my>>3)*h->mb_uvlinesize;
46
47     if(emu){
48         s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_cb, h->mb_uvlinesize, 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
49             src_cb= s->edge_emu_buffer;
50     }
51     chroma_op(dest_cb, src_cb, h->mb_uvlinesize, chroma_height, mx&7, my&7);
52
53     if(emu){
54         s->dsp.emulated_edge_mc(s->edge_emu_buffer, src_cr, h->mb_uvlinesize, 9, 9/*FIXME*/, (mx>>3), (my>>3), pic_width>>1, pic_height>>1);
55             src_cr= s->edge_emu_buffer;
56     }
57     chroma_op(dest_cr, src_cr, h->mb_uvlinesize, chroma_height, mx&7, my&7);
58 }
59
60 static inline void FUNC(mc_part_std)(H264Context *h, int n, int square, int chroma_height, int delta,
61                            uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
62                            int x_offset, int y_offset,
63                            qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
64                            qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg,
65                            int list0, int list1){
66     MpegEncContext * const s = &h->s;
67     qpel_mc_func *qpix_op=  qpix_put;
68     h264_chroma_mc_func chroma_op= chroma_put;
69
70     dest_y  += (2*x_offset<<PIXEL_SHIFT) + 2*y_offset*h->  mb_linesize;
71     dest_cb += (  x_offset<<PIXEL_SHIFT) +   y_offset*h->mb_uvlinesize;
72     dest_cr += (  x_offset<<PIXEL_SHIFT) +   y_offset*h->mb_uvlinesize;
73     x_offset += 8*s->mb_x;
74     y_offset += 8*(s->mb_y >> MB_FIELD);
75
76     if(list0){
77         Picture *ref= &h->ref_list[0][ h->ref_cache[0][ scan8[n] ] ];
78         FUNC(mc_dir_part)(h, ref, n, square, chroma_height, delta, 0,
79                            dest_y, dest_cb, dest_cr, x_offset, y_offset,
80                            qpix_op, chroma_op);
81
82         qpix_op=  qpix_avg;
83         chroma_op= chroma_avg;
84     }
85
86     if(list1){
87         Picture *ref= &h->ref_list[1][ h->ref_cache[1][ scan8[n] ] ];
88         FUNC(mc_dir_part)(h, ref, n, square, chroma_height, delta, 1,
89                            dest_y, dest_cb, dest_cr, x_offset, y_offset,
90                            qpix_op, chroma_op);
91     }
92 }
93
94 static inline void FUNC(mc_part_weighted)(H264Context *h, int n, int square, int chroma_height, int delta,
95                            uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
96                            int x_offset, int y_offset,
97                            qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
98                            h264_weight_func luma_weight_op, h264_weight_func chroma_weight_op,
99                            h264_biweight_func luma_weight_avg, h264_biweight_func chroma_weight_avg,
100                            int list0, int list1){
101     MpegEncContext * const s = &h->s;
102
103     dest_y  += (2*x_offset<<PIXEL_SHIFT) + 2*y_offset*h->  mb_linesize;
104     dest_cb += (  x_offset<<PIXEL_SHIFT) +   y_offset*h->mb_uvlinesize;
105     dest_cr += (  x_offset<<PIXEL_SHIFT) +   y_offset*h->mb_uvlinesize;
106     x_offset += 8*s->mb_x;
107     y_offset += 8*(s->mb_y >> MB_FIELD);
108
109     if(list0 && list1){
110         /* don't optimize for luma-only case, since B-frames usually
111          * use implicit weights => chroma too. */
112         uint8_t *tmp_cb = s->obmc_scratchpad;
113         uint8_t *tmp_cr = s->obmc_scratchpad + (8<<PIXEL_SHIFT);
114         uint8_t *tmp_y  = s->obmc_scratchpad + 8*h->mb_uvlinesize;
115         int refn0 = h->ref_cache[0][ scan8[n] ];
116         int refn1 = h->ref_cache[1][ scan8[n] ];
117
118         FUNC(mc_dir_part)(h, &h->ref_list[0][refn0], n, square, chroma_height, delta, 0,
119                     dest_y, dest_cb, dest_cr,
120                     x_offset, y_offset, qpix_put, chroma_put);
121         FUNC(mc_dir_part)(h, &h->ref_list[1][refn1], n, square, chroma_height, delta, 1,
122                     tmp_y, tmp_cb, tmp_cr,
123                     x_offset, y_offset, qpix_put, chroma_put);
124
125         if(h->use_weight == 2){
126             int weight0 = h->implicit_weight[refn0][refn1][s->mb_y&1];
127             int weight1 = 64 - weight0;
128             luma_weight_avg(  dest_y,  tmp_y,  h->  mb_linesize, 5, weight0, weight1, 0);
129             chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, 5, weight0, weight1, 0);
130             chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, 5, weight0, weight1, 0);
131         }else{
132             luma_weight_avg(dest_y, tmp_y, h->mb_linesize, h->luma_log2_weight_denom,
133                             h->luma_weight[refn0][0][0] , h->luma_weight[refn1][1][0],
134                             h->luma_weight[refn0][0][1] + h->luma_weight[refn1][1][1]);
135             chroma_weight_avg(dest_cb, tmp_cb, h->mb_uvlinesize, h->chroma_log2_weight_denom,
136                             h->chroma_weight[refn0][0][0][0] , h->chroma_weight[refn1][1][0][0],
137                             h->chroma_weight[refn0][0][0][1] + h->chroma_weight[refn1][1][0][1]);
138             chroma_weight_avg(dest_cr, tmp_cr, h->mb_uvlinesize, h->chroma_log2_weight_denom,
139                             h->chroma_weight[refn0][0][1][0] , h->chroma_weight[refn1][1][1][0],
140                             h->chroma_weight[refn0][0][1][1] + h->chroma_weight[refn1][1][1][1]);
141         }
142     }else{
143         int list = list1 ? 1 : 0;
144         int refn = h->ref_cache[list][ scan8[n] ];
145         Picture *ref= &h->ref_list[list][refn];
146         FUNC(mc_dir_part)(h, ref, n, square, chroma_height, delta, list,
147                     dest_y, dest_cb, dest_cr, x_offset, y_offset,
148                     qpix_put, chroma_put);
149
150         luma_weight_op(dest_y, h->mb_linesize, h->luma_log2_weight_denom,
151                        h->luma_weight[refn][list][0], h->luma_weight[refn][list][1]);
152         if(h->use_weight_chroma){
153             chroma_weight_op(dest_cb, h->mb_uvlinesize, h->chroma_log2_weight_denom,
154                              h->chroma_weight[refn][list][0][0], h->chroma_weight[refn][list][0][1]);
155             chroma_weight_op(dest_cr, h->mb_uvlinesize, h->chroma_log2_weight_denom,
156                              h->chroma_weight[refn][list][1][0], h->chroma_weight[refn][list][1][1]);
157         }
158     }
159 }
160
161 static inline void FUNC(mc_part)(H264Context *h, int n, int square, int chroma_height, int delta,
162                            uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
163                            int x_offset, int y_offset,
164                            qpel_mc_func *qpix_put, h264_chroma_mc_func chroma_put,
165                            qpel_mc_func *qpix_avg, h264_chroma_mc_func chroma_avg,
166                            h264_weight_func *weight_op, h264_biweight_func *weight_avg,
167                            int list0, int list1){
168     if((h->use_weight==2 && list0 && list1
169         && (h->implicit_weight[ h->ref_cache[0][scan8[n]] ][ h->ref_cache[1][scan8[n]] ][h->s.mb_y&1] != 32))
170        || h->use_weight==1)
171         FUNC(mc_part_weighted)(h, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
172                          x_offset, y_offset, qpix_put, chroma_put,
173                          weight_op[0], weight_op[3], weight_avg[0], weight_avg[3], list0, list1);
174     else
175         FUNC(mc_part_std)(h, n, square, chroma_height, delta, dest_y, dest_cb, dest_cr,
176                     x_offset, y_offset, qpix_put, chroma_put, qpix_avg, chroma_avg, list0, list1);
177 }
178
179 static inline void FUNC(prefetch_motion)(H264Context *h, int list){
180     /* fetch pixels for estimated mv 4 macroblocks ahead
181      * optimized for 64byte cache lines */
182     MpegEncContext * const s = &h->s;
183     const int refn = h->ref_cache[list][scan8[0]];
184     if(refn >= 0){
185         const int mx= (h->mv_cache[list][scan8[0]][0]>>2) + 16*s->mb_x + 8;
186         const int my= (h->mv_cache[list][scan8[0]][1]>>2) + 16*s->mb_y;
187         uint8_t **src= h->ref_list[list][refn].data;
188         int off= ((mx+64)<<PIXEL_SHIFT) + (my + (s->mb_x&3)*4)*h->mb_linesize;
189         s->dsp.prefetch(src[0]+off, s->linesize, 4);
190         off= (((mx>>1)+64)<<PIXEL_SHIFT) + ((my>>1) + (s->mb_x&7))*s->uvlinesize;
191         s->dsp.prefetch(src[1]+off, src[2]-src[1], 2);
192     }
193 }
194
195 static void FUNC(hl_motion)(H264Context *h, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
196                       qpel_mc_func (*qpix_put)[16], h264_chroma_mc_func (*chroma_put),
197                       qpel_mc_func (*qpix_avg)[16], h264_chroma_mc_func (*chroma_avg),
198                       h264_weight_func *weight_op, h264_biweight_func *weight_avg){
199     MpegEncContext * const s = &h->s;
200     const int mb_xy= h->mb_xy;
201     const int mb_type= s->current_picture.mb_type[mb_xy];
202
203     assert(IS_INTER(mb_type));
204
205     if(HAVE_PTHREADS && s->avctx->active_thread_type&FF_THREAD_FRAME)
206         await_references(h);
207     FUNC(prefetch_motion)(h, 0);
208
209     if(IS_16X16(mb_type)){
210         FUNC(mc_part)(h, 0, 1, 8, 0, dest_y, dest_cb, dest_cr, 0, 0,
211                 qpix_put[0], chroma_put[0], qpix_avg[0], chroma_avg[0],
212                 weight_op, weight_avg,
213                 IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
214     }else if(IS_16X8(mb_type)){
215         FUNC(mc_part)(h, 0, 0, 4, (8<<PIXEL_SHIFT), dest_y, dest_cb, dest_cr, 0, 0,
216                 qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
217                 &weight_op[1], &weight_avg[1],
218                 IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
219         FUNC(mc_part)(h, 8, 0, 4, (8<<PIXEL_SHIFT), dest_y, dest_cb, dest_cr, 0, 4,
220                 qpix_put[1], chroma_put[0], qpix_avg[1], chroma_avg[0],
221                 &weight_op[1], &weight_avg[1],
222                 IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1));
223     }else if(IS_8X16(mb_type)){
224         FUNC(mc_part)(h, 0, 0, 8, 8*h->mb_linesize, dest_y, dest_cb, dest_cr, 0, 0,
225                 qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
226                 &weight_op[2], &weight_avg[2],
227                 IS_DIR(mb_type, 0, 0), IS_DIR(mb_type, 0, 1));
228         FUNC(mc_part)(h, 4, 0, 8, 8*h->mb_linesize, dest_y, dest_cb, dest_cr, 4, 0,
229                 qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
230                 &weight_op[2], &weight_avg[2],
231                 IS_DIR(mb_type, 1, 0), IS_DIR(mb_type, 1, 1));
232     }else{
233         int i;
234
235         assert(IS_8X8(mb_type));
236
237         for(i=0; i<4; i++){
238             const int sub_mb_type= h->sub_mb_type[i];
239             const int n= 4*i;
240             int x_offset= (i&1)<<2;
241             int y_offset= (i&2)<<1;
242
243             if(IS_SUB_8X8(sub_mb_type)){
244                 FUNC(mc_part)(h, n, 1, 4, 0, dest_y, dest_cb, dest_cr, x_offset, y_offset,
245                     qpix_put[1], chroma_put[1], qpix_avg[1], chroma_avg[1],
246                     &weight_op[3], &weight_avg[3],
247                     IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
248             }else if(IS_SUB_8X4(sub_mb_type)){
249                 FUNC(mc_part)(h, n  , 0, 2, (4<<PIXEL_SHIFT), dest_y, dest_cb, dest_cr, x_offset, y_offset,
250                     qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
251                     &weight_op[4], &weight_avg[4],
252                     IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
253                 FUNC(mc_part)(h, n+2, 0, 2, (4<<PIXEL_SHIFT), dest_y, dest_cb, dest_cr, x_offset, y_offset+2,
254                     qpix_put[2], chroma_put[1], qpix_avg[2], chroma_avg[1],
255                     &weight_op[4], &weight_avg[4],
256                     IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
257             }else if(IS_SUB_4X8(sub_mb_type)){
258                 FUNC(mc_part)(h, n  , 0, 4, 4*h->mb_linesize, dest_y, dest_cb, dest_cr, x_offset, y_offset,
259                     qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
260                     &weight_op[5], &weight_avg[5],
261                     IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
262                 FUNC(mc_part)(h, n+1, 0, 4, 4*h->mb_linesize, dest_y, dest_cb, dest_cr, x_offset+2, y_offset,
263                     qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
264                     &weight_op[5], &weight_avg[5],
265                     IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
266             }else{
267                 int j;
268                 assert(IS_SUB_4X4(sub_mb_type));
269                 for(j=0; j<4; j++){
270                     int sub_x_offset= x_offset + 2*(j&1);
271                     int sub_y_offset= y_offset +   (j&2);
272                     FUNC(mc_part)(h, n+j, 1, 2, 0, dest_y, dest_cb, dest_cr, sub_x_offset, sub_y_offset,
273                         qpix_put[2], chroma_put[2], qpix_avg[2], chroma_avg[2],
274                         &weight_op[6], &weight_avg[6],
275                         IS_DIR(sub_mb_type, 0, 0), IS_DIR(sub_mb_type, 0, 1));
276                 }
277             }
278         }
279     }
280
281     FUNC(prefetch_motion)(h, 1);
282 }