ffmpeg / libavcodec / h264_direct.c @ 923bcb40
History | View | Annotate | Download (24.7 KB)
1 |
/*
|
---|---|
2 |
* H.26L/H.264/AVC/JVT/14496-10/... direct mb/block decoding
|
3 |
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
4 |
*
|
5 |
* This file is part of FFmpeg.
|
6 |
*
|
7 |
* FFmpeg is free software; you can redistribute it and/or
|
8 |
* modify it under the terms of the GNU Lesser General Public
|
9 |
* License as published by the Free Software Foundation; either
|
10 |
* version 2.1 of the License, or (at your option) any later version.
|
11 |
*
|
12 |
* FFmpeg is distributed in the hope that it will be useful,
|
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 |
* Lesser General Public License for more details.
|
16 |
*
|
17 |
* You should have received a copy of the GNU Lesser General Public
|
18 |
* License along with FFmpeg; if not, write to the Free Software
|
19 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
20 |
*/
|
21 |
|
22 |
/**
|
23 |
* @file libavcodec/h264_direct.c
|
24 |
* H.264 / AVC / MPEG4 part10 direct mb/block decoding.
|
25 |
* @author Michael Niedermayer <michaelni@gmx.at>
|
26 |
*/
|
27 |
|
28 |
#include "internal.h" |
29 |
#include "dsputil.h" |
30 |
#include "avcodec.h" |
31 |
#include "mpegvideo.h" |
32 |
#include "h264.h" |
33 |
#include "rectangle.h" |
34 |
|
35 |
//#undef NDEBUG
|
36 |
#include <assert.h> |
37 |
|
38 |
|
39 |
static int get_scale_factor(H264Context * const h, int poc, int poc1, int i){ |
40 |
int poc0 = h->ref_list[0][i].poc; |
41 |
int td = av_clip(poc1 - poc0, -128, 127); |
42 |
if(td == 0 || h->ref_list[0][i].long_ref){ |
43 |
return 256; |
44 |
}else{
|
45 |
int tb = av_clip(poc - poc0, -128, 127); |
46 |
int tx = (16384 + (FFABS(td) >> 1)) / td; |
47 |
return av_clip((tb*tx + 32) >> 6, -1024, 1023); |
48 |
} |
49 |
} |
50 |
|
51 |
void ff_h264_direct_dist_scale_factor(H264Context * const h){ |
52 |
MpegEncContext * const s = &h->s;
|
53 |
const int poc = h->s.current_picture_ptr->field_poc[ s->picture_structure == PICT_BOTTOM_FIELD ]; |
54 |
const int poc1 = h->ref_list[1][0].poc; |
55 |
int i, field;
|
56 |
for(field=0; field<2; field++){ |
57 |
const int poc = h->s.current_picture_ptr->field_poc[field]; |
58 |
const int poc1 = h->ref_list[1][0].field_poc[field]; |
59 |
for(i=0; i < 2*h->ref_count[0]; i++) |
60 |
h->dist_scale_factor_field[field][i^field] = get_scale_factor(h, poc, poc1, i+16);
|
61 |
} |
62 |
|
63 |
for(i=0; i<h->ref_count[0]; i++){ |
64 |
h->dist_scale_factor[i] = get_scale_factor(h, poc, poc1, i); |
65 |
} |
66 |
} |
67 |
|
68 |
static void fill_colmap(H264Context *h, int map[2][16+32], int list, int field, int colfield, int mbafi){ |
69 |
MpegEncContext * const s = &h->s;
|
70 |
Picture * const ref1 = &h->ref_list[1][0]; |
71 |
int j, old_ref, rfield;
|
72 |
int start= mbafi ? 16 : 0; |
73 |
int end = mbafi ? 16+2*h->ref_count[0] : h->ref_count[0]; |
74 |
int interl= mbafi || s->picture_structure != PICT_FRAME;
|
75 |
|
76 |
/* bogus; fills in for missing frames */
|
77 |
memset(map[list], 0, sizeof(map[list])); |
78 |
|
79 |
for(rfield=0; rfield<2; rfield++){ |
80 |
for(old_ref=0; old_ref<ref1->ref_count[colfield][list]; old_ref++){ |
81 |
int poc = ref1->ref_poc[colfield][list][old_ref];
|
82 |
|
83 |
if (!interl)
|
84 |
poc |= 3;
|
85 |
else if( interl && (poc&3) == 3) //FIXME store all MBAFF references so this isnt needed |
86 |
poc= (poc&~3) + rfield + 1; |
87 |
|
88 |
for(j=start; j<end; j++){
|
89 |
if(4*h->ref_list[0][j].frame_num + (h->ref_list[0][j].reference&3) == poc){ |
90 |
int cur_ref= mbafi ? (j-16)^field : j; |
91 |
map[list][2*old_ref + (rfield^field) + 16] = cur_ref; |
92 |
if(rfield == field || !interl)
|
93 |
map[list][old_ref] = cur_ref; |
94 |
break;
|
95 |
} |
96 |
} |
97 |
} |
98 |
} |
99 |
} |
100 |
|
101 |
void ff_h264_direct_ref_list_init(H264Context * const h){ |
102 |
MpegEncContext * const s = &h->s;
|
103 |
Picture * const ref1 = &h->ref_list[1][0]; |
104 |
Picture * const cur = s->current_picture_ptr;
|
105 |
int list, j, field;
|
106 |
int sidx= (s->picture_structure&1)^1; |
107 |
int ref1sidx= (ref1->reference&1)^1; |
108 |
|
109 |
for(list=0; list<2; list++){ |
110 |
cur->ref_count[sidx][list] = h->ref_count[list]; |
111 |
for(j=0; j<h->ref_count[list]; j++) |
112 |
cur->ref_poc[sidx][list][j] = 4*h->ref_list[list][j].frame_num + (h->ref_list[list][j].reference&3); |
113 |
} |
114 |
|
115 |
if(s->picture_structure == PICT_FRAME){
|
116 |
memcpy(cur->ref_count[1], cur->ref_count[0], sizeof(cur->ref_count[0])); |
117 |
memcpy(cur->ref_poc [1], cur->ref_poc [0], sizeof(cur->ref_poc [0])); |
118 |
} |
119 |
|
120 |
cur->mbaff= FRAME_MBAFF; |
121 |
|
122 |
h->col_fieldoff= 0;
|
123 |
if(s->picture_structure == PICT_FRAME){
|
124 |
int cur_poc = s->current_picture_ptr->poc;
|
125 |
int *col_poc = h->ref_list[1]->field_poc; |
126 |
h->col_parity= (FFABS(col_poc[0] - cur_poc) >= FFABS(col_poc[1] - cur_poc)); |
127 |
ref1sidx=sidx= h->col_parity; |
128 |
}else if(!(s->picture_structure & h->ref_list[1][0].reference) && !h->ref_list[1][0].mbaff){ // FL -> FL & differ parity |
129 |
h->col_fieldoff= s->mb_stride*(2*(h->ref_list[1][0].reference) - 3); |
130 |
} |
131 |
|
132 |
if(cur->pict_type != FF_B_TYPE || h->direct_spatial_mv_pred)
|
133 |
return;
|
134 |
|
135 |
for(list=0; list<2; list++){ |
136 |
fill_colmap(h, h->map_col_to_list0, list, sidx, ref1sidx, 0);
|
137 |
if(FRAME_MBAFF)
|
138 |
for(field=0; field<2; field++) |
139 |
fill_colmap(h, h->map_col_to_list0_field[field], list, field, field, 1);
|
140 |
} |
141 |
} |
142 |
|
143 |
static void pred_spatial_direct_motion(H264Context * const h, int *mb_type){ |
144 |
MpegEncContext * const s = &h->s;
|
145 |
int b8_stride = h->b8_stride;
|
146 |
int b4_stride = h->b_stride;
|
147 |
int mb_xy = h->mb_xy;
|
148 |
int mb_type_col[2]; |
149 |
const int16_t (*l1mv0)[2], (*l1mv1)[2]; |
150 |
const int8_t *l1ref0, *l1ref1;
|
151 |
const int is_b8x8 = IS_8X8(*mb_type); |
152 |
unsigned int sub_mb_type; |
153 |
int i8, i4;
|
154 |
int ref[2]; |
155 |
int mv[2]; |
156 |
int list;
|
157 |
|
158 |
assert(h->ref_list[1][0].reference&3); |
159 |
|
160 |
#define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)
|
161 |
|
162 |
*mb_type |= MB_TYPE_L0L1; |
163 |
sub_mb_type |= MB_TYPE_L0L1; |
164 |
|
165 |
/* ref = min(neighbors) */
|
166 |
for(list=0; list<2; list++){ |
167 |
int left_ref = h->ref_cache[list][scan8[0] - 1]; |
168 |
int top_ref = h->ref_cache[list][scan8[0] - 8]; |
169 |
int refc = h->ref_cache[list][scan8[0] - 8 + 4]; |
170 |
const int16_t *C= h->mv_cache[list][ scan8[0] - 8 + 4]; |
171 |
if(refc == PART_NOT_AVAILABLE){
|
172 |
refc = h->ref_cache[list][scan8[0] - 8 - 1]; |
173 |
C = h-> mv_cache[list][scan8[0] - 8 - 1]; |
174 |
} |
175 |
ref[list] = FFMIN3((unsigned)left_ref, (unsigned)top_ref, (unsigned)refc); |
176 |
if(ref[list] >= 0){ |
177 |
//this is just pred_motion() but with the cases removed that cannot happen for direct blocks
|
178 |
const int16_t * const A= h->mv_cache[list][ scan8[0] - 1 ]; |
179 |
const int16_t * const B= h->mv_cache[list][ scan8[0] - 8 ]; |
180 |
|
181 |
int match_count= (left_ref==ref[list]) + (top_ref==ref[list]) + (refc==ref[list]);
|
182 |
if(match_count > 1){ //most common |
183 |
mv[list]= (mid_pred(A[0], B[0], C[0])&0xFFFF) |
184 |
+(mid_pred(A[1], B[1], C[1])<<16); |
185 |
}else {
|
186 |
assert(match_count==1);
|
187 |
if(left_ref==ref[list]){
|
188 |
mv[list]= *(uint32_t*)A; |
189 |
}else if(top_ref==ref[list]){ |
190 |
mv[list]= *(uint32_t*)B; |
191 |
}else{
|
192 |
mv[list]= *(uint32_t*)C; |
193 |
} |
194 |
} |
195 |
}else{
|
196 |
int mask= ~(MB_TYPE_L0 << (2*list)); |
197 |
mv[list] = 0;
|
198 |
ref[list] = -1;
|
199 |
if(!is_b8x8)
|
200 |
*mb_type &= mask; |
201 |
sub_mb_type &= mask; |
202 |
} |
203 |
} |
204 |
if(ref[0] < 0 && ref[1] < 0){ |
205 |
ref[0] = ref[1] = 0; |
206 |
if(!is_b8x8)
|
207 |
*mb_type |= MB_TYPE_L0L1; |
208 |
sub_mb_type |= MB_TYPE_L0L1; |
209 |
} |
210 |
|
211 |
if(!is_b8x8 && (mv[0]|mv[1]) == 0){ |
212 |
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); |
213 |
fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); |
214 |
fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); |
215 |
fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4); |
216 |
*mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2; |
217 |
return;
|
218 |
} |
219 |
|
220 |
if(IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])){ // AFL/AFR/FR/FL -> AFL/FL |
221 |
if(!IS_INTERLACED(*mb_type)){ // AFR/FR -> AFL/FL |
222 |
mb_xy= s->mb_x + ((s->mb_y&~1) + h->col_parity)*s->mb_stride;
|
223 |
b8_stride = 0;
|
224 |
}else{
|
225 |
mb_xy += h->col_fieldoff; // non zero for FL -> FL & differ parity
|
226 |
} |
227 |
goto single_col;
|
228 |
}else{ // AFL/AFR/FR/FL -> AFR/FR |
229 |
if(IS_INTERLACED(*mb_type)){ // AFL /FL -> AFR/FR |
230 |
mb_xy= s->mb_x + (s->mb_y&~1)*s->mb_stride;
|
231 |
mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; |
232 |
mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + s->mb_stride]; |
233 |
b8_stride *= 3;
|
234 |
b4_stride *= 6;
|
235 |
|
236 |
sub_mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
237 |
if( (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA) |
238 |
&& (mb_type_col[1] & MB_TYPE_16x16_OR_INTRA)
|
239 |
&& !is_b8x8){ |
240 |
*mb_type |= MB_TYPE_16x8 |MB_TYPE_DIRECT2; /* B_16x8 */
|
241 |
}else{
|
242 |
*mb_type |= MB_TYPE_8x8; |
243 |
} |
244 |
}else{ // AFR/FR -> AFR/FR |
245 |
single_col:
|
246 |
mb_type_col[0] =
|
247 |
mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy]; |
248 |
|
249 |
sub_mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
250 |
if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){ |
251 |
*mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_16x16 */
|
252 |
}else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){ |
253 |
*mb_type |= MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));
|
254 |
}else{
|
255 |
if(!h->sps.direct_8x8_inference_flag){
|
256 |
/* FIXME save sub mb types from previous frames (or derive from MVs)
|
257 |
* so we know exactly what block size to use */
|
258 |
sub_mb_type += (MB_TYPE_8x8-MB_TYPE_16x16); /* B_SUB_4x4 */
|
259 |
} |
260 |
*mb_type |= MB_TYPE_8x8; |
261 |
} |
262 |
} |
263 |
} |
264 |
|
265 |
l1mv0 = &h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]]; |
266 |
l1mv1 = &h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]]; |
267 |
l1ref0 = &h->ref_list[1][0].ref_index [0][h->mb2b8_xy[mb_xy]]; |
268 |
l1ref1 = &h->ref_list[1][0].ref_index [1][h->mb2b8_xy[mb_xy]]; |
269 |
if(!b8_stride){
|
270 |
if(s->mb_y&1){ |
271 |
l1ref0 += h->b8_stride; |
272 |
l1ref1 += h->b8_stride; |
273 |
l1mv0 += 2*b4_stride;
|
274 |
l1mv1 += 2*b4_stride;
|
275 |
} |
276 |
} |
277 |
|
278 |
|
279 |
if(IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])){ |
280 |
int n=0; |
281 |
for(i8=0; i8<4; i8++){ |
282 |
int x8 = i8&1; |
283 |
int y8 = i8>>1; |
284 |
int xy8 = x8+y8*b8_stride;
|
285 |
int xy4 = 3*x8+y8*b4_stride; |
286 |
int a,b;
|
287 |
|
288 |
if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))
|
289 |
continue;
|
290 |
h->sub_mb_type[i8] = sub_mb_type; |
291 |
|
292 |
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[0], 1); |
293 |
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[1], 1); |
294 |
if(!IS_INTRA(mb_type_col[y8]) && !h->ref_list[1][0].long_ref |
295 |
&& ( (l1ref0[xy8] == 0 && FFABS(l1mv0[xy4][0]) <= 1 && FFABS(l1mv0[xy4][1]) <= 1) |
296 |
|| (l1ref0[xy8] < 0 && l1ref1[xy8] == 0 && FFABS(l1mv1[xy4][0]) <= 1 && FFABS(l1mv1[xy4][1]) <= 1))){ |
297 |
a=b=0;
|
298 |
if(ref[0] > 0) |
299 |
a= mv[0];
|
300 |
if(ref[1] > 0) |
301 |
b= mv[1];
|
302 |
n++; |
303 |
}else{
|
304 |
a= mv[0];
|
305 |
b= mv[1];
|
306 |
} |
307 |
fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, a, 4); |
308 |
fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, b, 4); |
309 |
} |
310 |
if(!is_b8x8 && !(n&3)) |
311 |
*mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2; |
312 |
}else if(IS_16X16(*mb_type)){ |
313 |
int a,b;
|
314 |
|
315 |
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1); |
316 |
fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1); |
317 |
if(!IS_INTRA(mb_type_col[0]) && !h->ref_list[1][0].long_ref |
318 |
&& ( (l1ref0[0] == 0 && FFABS(l1mv0[0][0]) <= 1 && FFABS(l1mv0[0][1]) <= 1) |
319 |
|| (l1ref0[0] < 0 && l1ref1[0] == 0 && FFABS(l1mv1[0][0]) <= 1 && FFABS(l1mv1[0][1]) <= 1 |
320 |
&& h->x264_build>33U))){
|
321 |
a=b=0;
|
322 |
if(ref[0] > 0) |
323 |
a= mv[0];
|
324 |
if(ref[1] > 0) |
325 |
b= mv[1];
|
326 |
}else{
|
327 |
a= mv[0];
|
328 |
b= mv[1];
|
329 |
} |
330 |
fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, a, 4); |
331 |
fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, b, 4); |
332 |
}else{
|
333 |
int n=0; |
334 |
for(i8=0; i8<4; i8++){ |
335 |
const int x8 = i8&1; |
336 |
const int y8 = i8>>1; |
337 |
|
338 |
if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))
|
339 |
continue;
|
340 |
h->sub_mb_type[i8] = sub_mb_type; |
341 |
|
342 |
fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, mv[0], 4); |
343 |
fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, mv[1], 4); |
344 |
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[0], 1); |
345 |
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[1], 1); |
346 |
|
347 |
/* col_zero_flag */
|
348 |
if(!IS_INTRA(mb_type_col[0]) && !h->ref_list[1][0].long_ref && ( l1ref0[x8 + y8*b8_stride] == 0 |
349 |
|| (l1ref0[x8 + y8*b8_stride] < 0 && l1ref1[x8 + y8*b8_stride] == 0 |
350 |
&& h->x264_build>33U))){
|
351 |
const int16_t (*l1mv)[2]= l1ref0[x8 + y8*b8_stride] == 0 ? l1mv0 : l1mv1; |
352 |
if(IS_SUB_8X8(sub_mb_type)){
|
353 |
const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride]; |
354 |
if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){ |
355 |
if(ref[0] == 0) |
356 |
fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4); |
357 |
if(ref[1] == 0) |
358 |
fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4); |
359 |
n+=4;
|
360 |
} |
361 |
}else{
|
362 |
int m=0; |
363 |
for(i4=0; i4<4; i4++){ |
364 |
const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride]; |
365 |
if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){ |
366 |
if(ref[0] == 0) |
367 |
*(uint32_t*)h->mv_cache[0][scan8[i8*4+i4]] = 0; |
368 |
if(ref[1] == 0) |
369 |
*(uint32_t*)h->mv_cache[1][scan8[i8*4+i4]] = 0; |
370 |
m++; |
371 |
} |
372 |
} |
373 |
if(!(m&3)) |
374 |
h->sub_mb_type[i8]+= MB_TYPE_16x16 - MB_TYPE_8x8; |
375 |
n+=m; |
376 |
} |
377 |
} |
378 |
} |
379 |
if(!is_b8x8 && !(n&15)) |
380 |
*mb_type= (*mb_type & ~(MB_TYPE_8x8|MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_P1L0|MB_TYPE_P1L1))|MB_TYPE_16x16|MB_TYPE_DIRECT2; |
381 |
} |
382 |
} |
383 |
|
384 |
static void pred_temp_direct_motion(H264Context * const h, int *mb_type){ |
385 |
MpegEncContext * const s = &h->s;
|
386 |
int b8_stride = h->b8_stride;
|
387 |
int b4_stride = h->b_stride;
|
388 |
int mb_xy = h->mb_xy;
|
389 |
int mb_type_col[2]; |
390 |
const int16_t (*l1mv0)[2], (*l1mv1)[2]; |
391 |
const int8_t *l1ref0, *l1ref1;
|
392 |
const int is_b8x8 = IS_8X8(*mb_type); |
393 |
unsigned int sub_mb_type; |
394 |
int i8, i4;
|
395 |
|
396 |
assert(h->ref_list[1][0].reference&3); |
397 |
|
398 |
if(IS_INTERLACED(h->ref_list[1][0].mb_type[mb_xy])){ // AFL/AFR/FR/FL -> AFL/FL |
399 |
if(!IS_INTERLACED(*mb_type)){ // AFR/FR -> AFL/FL |
400 |
mb_xy= s->mb_x + ((s->mb_y&~1) + h->col_parity)*s->mb_stride;
|
401 |
b8_stride = 0;
|
402 |
}else{
|
403 |
mb_xy += h->col_fieldoff; // non zero for FL -> FL & differ parity
|
404 |
} |
405 |
goto single_col;
|
406 |
}else{ // AFL/AFR/FR/FL -> AFR/FR |
407 |
if(IS_INTERLACED(*mb_type)){ // AFL /FL -> AFR/FR |
408 |
mb_xy= s->mb_x + (s->mb_y&~1)*s->mb_stride;
|
409 |
mb_type_col[0] = h->ref_list[1][0].mb_type[mb_xy]; |
410 |
mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy + s->mb_stride]; |
411 |
b8_stride *= 3;
|
412 |
b4_stride *= 6;
|
413 |
|
414 |
sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
415 |
|
416 |
if( (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA) |
417 |
&& (mb_type_col[1] & MB_TYPE_16x16_OR_INTRA)
|
418 |
&& !is_b8x8){ |
419 |
*mb_type |= MB_TYPE_16x8 |MB_TYPE_L0L1|MB_TYPE_DIRECT2; /* B_16x8 */
|
420 |
}else{
|
421 |
*mb_type |= MB_TYPE_8x8|MB_TYPE_L0L1; |
422 |
} |
423 |
}else{ // AFR/FR -> AFR/FR |
424 |
single_col:
|
425 |
mb_type_col[0] =
|
426 |
mb_type_col[1] = h->ref_list[1][0].mb_type[mb_xy]; |
427 |
|
428 |
sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
429 |
if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){ |
430 |
*mb_type |= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */
|
431 |
}else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){ |
432 |
*mb_type |= MB_TYPE_L0L1|MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));
|
433 |
}else{
|
434 |
if(!h->sps.direct_8x8_inference_flag){
|
435 |
/* FIXME save sub mb types from previous frames (or derive from MVs)
|
436 |
* so we know exactly what block size to use */
|
437 |
sub_mb_type = MB_TYPE_8x8|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_4x4 */
|
438 |
} |
439 |
*mb_type |= MB_TYPE_8x8|MB_TYPE_L0L1; |
440 |
} |
441 |
} |
442 |
} |
443 |
|
444 |
l1mv0 = &h->ref_list[1][0].motion_val[0][h->mb2b_xy [mb_xy]]; |
445 |
l1mv1 = &h->ref_list[1][0].motion_val[1][h->mb2b_xy [mb_xy]]; |
446 |
l1ref0 = &h->ref_list[1][0].ref_index [0][h->mb2b8_xy[mb_xy]]; |
447 |
l1ref1 = &h->ref_list[1][0].ref_index [1][h->mb2b8_xy[mb_xy]]; |
448 |
if(!b8_stride){
|
449 |
if(s->mb_y&1){ |
450 |
l1ref0 += h->b8_stride; |
451 |
l1ref1 += h->b8_stride; |
452 |
l1mv0 += 2*b4_stride;
|
453 |
l1mv1 += 2*b4_stride;
|
454 |
} |
455 |
} |
456 |
|
457 |
{ |
458 |
const int *map_col_to_list0[2] = {h->map_col_to_list0[0], h->map_col_to_list0[1]}; |
459 |
const int *dist_scale_factor = h->dist_scale_factor; |
460 |
int ref_offset;
|
461 |
|
462 |
if(FRAME_MBAFF && IS_INTERLACED(*mb_type)){
|
463 |
map_col_to_list0[0] = h->map_col_to_list0_field[s->mb_y&1][0]; |
464 |
map_col_to_list0[1] = h->map_col_to_list0_field[s->mb_y&1][1]; |
465 |
dist_scale_factor =h->dist_scale_factor_field[s->mb_y&1];
|
466 |
} |
467 |
ref_offset = (h->ref_list[1][0].mbaff<<4) & (mb_type_col[0]>>3); //if(h->ref_list[1][0].mbaff && IS_INTERLACED(mb_type_col[0])) ref_offset=16 else 0 |
468 |
|
469 |
if(IS_INTERLACED(*mb_type) != IS_INTERLACED(mb_type_col[0])){ |
470 |
int y_shift = 2*!IS_INTERLACED(*mb_type); |
471 |
assert(h->sps.direct_8x8_inference_flag); |
472 |
|
473 |
for(i8=0; i8<4; i8++){ |
474 |
const int x8 = i8&1; |
475 |
const int y8 = i8>>1; |
476 |
int ref0, scale;
|
477 |
const int16_t (*l1mv)[2]= l1mv0; |
478 |
|
479 |
if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))
|
480 |
continue;
|
481 |
h->sub_mb_type[i8] = sub_mb_type; |
482 |
|
483 |
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1); |
484 |
if(IS_INTRA(mb_type_col[y8])){
|
485 |
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1); |
486 |
fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4); |
487 |
fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4); |
488 |
continue;
|
489 |
} |
490 |
|
491 |
ref0 = l1ref0[x8 + y8*b8_stride]; |
492 |
if(ref0 >= 0) |
493 |
ref0 = map_col_to_list0[0][ref0 + ref_offset];
|
494 |
else{
|
495 |
ref0 = map_col_to_list0[1][l1ref1[x8 + y8*b8_stride] + ref_offset];
|
496 |
l1mv= l1mv1; |
497 |
} |
498 |
scale = dist_scale_factor[ref0]; |
499 |
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1); |
500 |
|
501 |
{ |
502 |
const int16_t *mv_col = l1mv[x8*3 + y8*b4_stride]; |
503 |
int my_col = (mv_col[1]<<y_shift)/2; |
504 |
int mx = (scale * mv_col[0] + 128) >> 8; |
505 |
int my = (scale * my_col + 128) >> 8; |
506 |
fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4); |
507 |
fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-my_col), 4); |
508 |
} |
509 |
} |
510 |
return;
|
511 |
} |
512 |
|
513 |
/* one-to-one mv scaling */
|
514 |
|
515 |
if(IS_16X16(*mb_type)){
|
516 |
int ref, mv0, mv1;
|
517 |
|
518 |
fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1); |
519 |
if(IS_INTRA(mb_type_col[0])){ |
520 |
ref=mv0=mv1=0;
|
521 |
}else{
|
522 |
const int ref0 = l1ref0[0] >= 0 ? map_col_to_list0[0][l1ref0[0] + ref_offset] |
523 |
: map_col_to_list0[1][l1ref1[0] + ref_offset]; |
524 |
const int scale = dist_scale_factor[ref0]; |
525 |
const int16_t *mv_col = l1ref0[0] >= 0 ? l1mv0[0] : l1mv1[0]; |
526 |
int mv_l0[2]; |
527 |
mv_l0[0] = (scale * mv_col[0] + 128) >> 8; |
528 |
mv_l0[1] = (scale * mv_col[1] + 128) >> 8; |
529 |
ref= ref0; |
530 |
mv0= pack16to32(mv_l0[0],mv_l0[1]); |
531 |
mv1= pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]); |
532 |
} |
533 |
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1); |
534 |
fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4); |
535 |
fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4); |
536 |
}else{
|
537 |
for(i8=0; i8<4; i8++){ |
538 |
const int x8 = i8&1; |
539 |
const int y8 = i8>>1; |
540 |
int ref0, scale;
|
541 |
const int16_t (*l1mv)[2]= l1mv0; |
542 |
|
543 |
if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))
|
544 |
continue;
|
545 |
h->sub_mb_type[i8] = sub_mb_type; |
546 |
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1); |
547 |
if(IS_INTRA(mb_type_col[0])){ |
548 |
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1); |
549 |
fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4); |
550 |
fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4); |
551 |
continue;
|
552 |
} |
553 |
|
554 |
ref0 = l1ref0[x8 + y8*b8_stride]; |
555 |
if(ref0 >= 0) |
556 |
ref0 = map_col_to_list0[0][ref0 + ref_offset];
|
557 |
else{
|
558 |
ref0 = map_col_to_list0[1][l1ref1[x8 + y8*b8_stride] + ref_offset];
|
559 |
l1mv= l1mv1; |
560 |
} |
561 |
scale = dist_scale_factor[ref0]; |
562 |
|
563 |
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1); |
564 |
if(IS_SUB_8X8(sub_mb_type)){
|
565 |
const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride]; |
566 |
int mx = (scale * mv_col[0] + 128) >> 8; |
567 |
int my = (scale * mv_col[1] + 128) >> 8; |
568 |
fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4); |
569 |
fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-mv_col[1]), 4); |
570 |
}else
|
571 |
for(i4=0; i4<4; i4++){ |
572 |
const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride]; |
573 |
int16_t *mv_l0 = h->mv_cache[0][scan8[i8*4+i4]]; |
574 |
mv_l0[0] = (scale * mv_col[0] + 128) >> 8; |
575 |
mv_l0[1] = (scale * mv_col[1] + 128) >> 8; |
576 |
*(uint32_t*)h->mv_cache[1][scan8[i8*4+i4]] = |
577 |
pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]); |
578 |
} |
579 |
} |
580 |
} |
581 |
} |
582 |
} |
583 |
|
584 |
void ff_h264_pred_direct_motion(H264Context * const h, int *mb_type){ |
585 |
if(h->direct_spatial_mv_pred){
|
586 |
pred_spatial_direct_motion(h, mb_type); |
587 |
}else{
|
588 |
pred_temp_direct_motion(h, mb_type); |
589 |
} |
590 |
} |