Statistics
| Branch: | Revision:

ffmpeg / libavcodec / h264_hl_motion.h @ a50f0bea

History | View | Annotate | Download (14.2 KB)

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
}