| rev |
line source |
|
nengel@2
|
1 /*
|
|
nengel@2
|
2 * H.26L/H.264/AVC/JVT/14496-10/... direct mb/block decoding
|
|
nengel@2
|
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
|
|
nengel@2
|
4 *
|
|
nengel@2
|
5 * This file is part of FFmpeg.
|
|
nengel@2
|
6 *
|
|
nengel@2
|
7 * FFmpeg is free software; you can redistribute it and/or
|
|
nengel@2
|
8 * modify it under the terms of the GNU Lesser General Public
|
|
nengel@2
|
9 * License as published by the Free Software Foundation; either
|
|
nengel@2
|
10 * version 2.1 of the License, or (at your option) any later version.
|
|
nengel@2
|
11 *
|
|
nengel@2
|
12 * FFmpeg is distributed in the hope that it will be useful,
|
|
nengel@2
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
nengel@2
|
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
nengel@2
|
15 * Lesser General Public License for more details.
|
|
nengel@2
|
16 *
|
|
nengel@2
|
17 * You should have received a copy of the GNU Lesser General Public
|
|
nengel@2
|
18 * License along with FFmpeg; if not, write to the Free Software
|
|
nengel@2
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
nengel@2
|
20 */
|
|
nengel@2
|
21
|
|
nengel@2
|
22 /**
|
|
nengel@2
|
23 * @file
|
|
nengel@2
|
24 * H.264 / AVC / MPEG4 part10 direct mb/block decoding.
|
|
nengel@2
|
25 * @author Michael Niedermayer <michaelni@gmx.at>
|
|
nengel@2
|
26 */
|
|
nengel@2
|
27
|
|
nengel@2
|
28 #include "dsputil.h"
|
|
nengel@2
|
29 #include "avcodec.h"
|
|
nengel@2
|
30 #include "h264_data.h"
|
|
nengel@2
|
31 #include "h264.h"
|
|
nengel@2
|
32 #include "rectangle.h"
|
|
nengel@2
|
33
|
|
nengel@2
|
34 //#undef NDEBUG
|
|
nengel@2
|
35 #include <assert.h>
|
|
nengel@2
|
36
|
|
nengel@2
|
37 static const uint8_t left_block_options[4][16]={
|
|
nengel@2
|
38 {0,1,2,3,7,10,8,11,7+0*8, 7+1*8, 7+2*8, 7+3*8, 2+0*8, 2+3*8, 2+1*8, 2+2*8},
|
|
nengel@2
|
39 {2,2,3,3,8,11,8,11,7+2*8, 7+2*8, 7+3*8, 7+3*8, 2+1*8, 2+2*8, 2+1*8, 2+2*8},
|
|
nengel@2
|
40 {0,0,1,1,7,10,7,10,7+0*8, 7+0*8, 7+1*8, 7+1*8, 2+0*8, 2+3*8, 2+0*8, 2+3*8},
|
|
nengel@2
|
41 {0,2,0,2,7,10,7,10,7+0*8, 7+2*8, 7+0*8, 7+2*8, 2+0*8, 2+3*8, 2+0*8, 2+3*8}
|
|
nengel@2
|
42 };
|
|
nengel@2
|
43
|
|
nengel@2
|
44
|
|
nengel@2
|
45 // static void check_cache_copy(MBRecContext *mrc, H264Slice *s, H264Mb *m){
|
|
nengel@2
|
46 // for (int list=0; list<2; list++){
|
|
nengel@2
|
47 // for (int i=0; i<40; i++){
|
|
nengel@2
|
48 // assert (m->ref_cache[list][i] == m->ref_cache_copy[list][i]);
|
|
nengel@2
|
49 // assert (mrs->mv_cache[list][i][0] == mrs->mv_cache_copy[list][i][0]);
|
|
nengel@2
|
50 // assert (mrs->mv_cache[list][i][1] == mrs->mv_cache_copy[list][i][1]);
|
|
nengel@2
|
51 // }
|
|
nengel@2
|
52 // }
|
|
nengel@2
|
53 // }
|
|
nengel@2
|
54
|
|
nengel@2
|
55 // static void check_cache_copy2(MBRecContext *mrc, H264Slice *s, H264Mb *m){
|
|
nengel@2
|
56 // for (int list=0; list<2; list++){
|
|
nengel@2
|
57 // for (int i=0; i<40; i++){
|
|
nengel@2
|
58 // assert (m->ref_cache[list][i] == m->ref_cache_copy2[list][i]);
|
|
nengel@2
|
59 // assert (mrs->mv_cache[list][i][0] == mrs->mv_cache_copy2[list][i][0]);
|
|
nengel@2
|
60 // assert (mrs->mv_cache[list][i][1] == mrs->mv_cache_copy2[list][i][1]);
|
|
nengel@2
|
61 // }
|
|
nengel@2
|
62 // }
|
|
nengel@2
|
63 // }
|
|
nengel@2
|
64
|
|
nengel@2
|
65 static void fill_decode_caches_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mb_type){
|
|
nengel@2
|
66 int topleft_type, top_type, topright_type, left_type;
|
|
nengel@2
|
67 const uint8_t * left_block= left_block_options[0];
|
|
nengel@2
|
68 const int mb_x = m->mb_x;
|
|
nengel@2
|
69 int i;
|
|
nengel@2
|
70
|
|
nengel@2
|
71 mrs->top_type = mrs->mb_type_top[mb_x ];
|
|
nengel@2
|
72 mrs->left_type = mrs->mb_type [mb_x-1];
|
|
nengel@2
|
73
|
|
nengel@2
|
74 topleft_type = mrs->mb_type_top[mb_x-1];
|
|
nengel@2
|
75 top_type = mrs->mb_type_top[mb_x ];
|
|
nengel@2
|
76 topright_type= mrs->mb_type_top[mb_x+1];
|
|
nengel@2
|
77 left_type = mrs->mb_type [mb_x-1];
|
|
nengel@2
|
78
|
|
nengel@2
|
79 int type_mask= s->pps.constrained_intra_pred ? 1 : -1;
|
|
nengel@2
|
80
|
|
nengel@2
|
81 if(!IS_SKIP(mb_type)){
|
|
nengel@2
|
82 // memset(mrc->non_zero_count_cache, 0, sizeof(mrc->non_zero_count_cache));
|
|
nengel@2
|
83 AV_COPY32(&mrs->non_zero_count_cache[4+8*1], &m->non_zero_count[ 0]);
|
|
nengel@2
|
84 AV_COPY32(&mrs->non_zero_count_cache[4+8*2], &m->non_zero_count[ 4]);
|
|
nengel@2
|
85 AV_COPY32(&mrs->non_zero_count_cache[4+8*3], &m->non_zero_count[ 8]);
|
|
nengel@2
|
86 AV_COPY32(&mrs->non_zero_count_cache[4+8*4], &m->non_zero_count[12]);
|
|
nengel@2
|
87
|
|
nengel@2
|
88 for (int i=0; i<2; i++) {
|
|
nengel@2
|
89 mrs->non_zero_count_cache[8*1 + 8*i + 1] = m->non_zero_count[16 + i*2 ];
|
|
nengel@2
|
90 mrs->non_zero_count_cache[8*1 + 8*i + 2] = m->non_zero_count[16 + i*2 +1];
|
|
nengel@2
|
91 mrs->non_zero_count_cache[8*4 + 8*i + 1] = m->non_zero_count[20 + i*2 ];
|
|
nengel@2
|
92 mrs->non_zero_count_cache[8*4 + 8*i + 2] = m->non_zero_count[20 + i*2 +1];
|
|
nengel@2
|
93 }
|
|
nengel@2
|
94
|
|
nengel@2
|
95 if(IS_INTRA(mb_type)){
|
|
nengel@2
|
96 // memset(mrc->intra4x4_pred_mode_cache, 0, sizeof(mrc->intra4x4_pred_mode_cache));
|
|
nengel@2
|
97
|
|
nengel@2
|
98 mrs->topleft_samples_available=
|
|
nengel@2
|
99 mrs->top_samples_available=
|
|
nengel@2
|
100 mrs->left_samples_available= 0xFFFF;
|
|
nengel@2
|
101 mrs->topright_samples_available= 0xEEEA;
|
|
nengel@2
|
102
|
|
nengel@2
|
103 if(!(top_type & type_mask)){
|
|
nengel@2
|
104 mrs->topleft_samples_available= 0xB3FF;
|
|
nengel@2
|
105 mrs->top_samples_available= 0x33FF;
|
|
nengel@2
|
106 mrs->topright_samples_available= 0x26EA;
|
|
nengel@2
|
107 }
|
|
nengel@2
|
108
|
|
nengel@2
|
109 if(!(left_type & type_mask)){
|
|
nengel@2
|
110 mrs->topleft_samples_available&= 0xDF5F;
|
|
nengel@2
|
111 mrs->left_samples_available&= 0x5F5F;
|
|
nengel@2
|
112 }
|
|
nengel@2
|
113
|
|
nengel@2
|
114 if(!(topleft_type & type_mask))
|
|
nengel@2
|
115 mrs->topleft_samples_available&= 0x7FFF;
|
|
nengel@2
|
116
|
|
nengel@2
|
117 if(!(topright_type & type_mask))
|
|
nengel@2
|
118 mrs->topright_samples_available&= 0xFBFF;
|
|
nengel@2
|
119
|
|
nengel@2
|
120 if(IS_INTRA4x4(mb_type)){
|
|
nengel@2
|
121 if(IS_INTRA4x4(top_type)){
|
|
nengel@2
|
122 AV_COPY32(mrs->intra4x4_pred_mode_cache+4+8*0, &mrs->intra4x4_pred_mode_top[4*mb_x]);
|
|
nengel@2
|
123 }else{
|
|
nengel@2
|
124 mrs->intra4x4_pred_mode_cache[4+8*0]=
|
|
nengel@2
|
125 mrs->intra4x4_pred_mode_cache[5+8*0]=
|
|
nengel@2
|
126 mrs->intra4x4_pred_mode_cache[6+8*0]=
|
|
nengel@2
|
127 mrs->intra4x4_pred_mode_cache[7+8*0]= 2 - 3*!(top_type & type_mask);
|
|
nengel@2
|
128 }
|
|
nengel@2
|
129
|
|
nengel@2
|
130 if(IS_INTRA4x4(left_type)){
|
|
nengel@2
|
131 #if OMPSS
|
|
nengel@2
|
132 mrs->intra4x4_pred_mode_cache[3+8*1]= m->intra4x4_pred_mode_left[0];
|
|
nengel@2
|
133 mrs->intra4x4_pred_mode_cache[3+8*2]= m->intra4x4_pred_mode_left[1];
|
|
nengel@2
|
134 mrs->intra4x4_pred_mode_cache[3+8*3]= m->intra4x4_pred_mode_left[2];
|
|
nengel@2
|
135 mrs->intra4x4_pred_mode_cache[3+8*4]= m->intra4x4_pred_mode_left[3];
|
|
nengel@2
|
136 #else
|
|
nengel@2
|
137 mrs->intra4x4_pred_mode_cache[3+8*1]= mrs->intra4x4_pred_mode_left[0];
|
|
nengel@2
|
138 mrs->intra4x4_pred_mode_cache[3+8*2]= mrs->intra4x4_pred_mode_left[1];
|
|
nengel@2
|
139 mrs->intra4x4_pred_mode_cache[3+8*3]= mrs->intra4x4_pred_mode_left[2];
|
|
nengel@2
|
140 mrs->intra4x4_pred_mode_cache[3+8*4]= mrs->intra4x4_pred_mode_left[3];
|
|
nengel@2
|
141 #endif
|
|
nengel@2
|
142 }else{
|
|
nengel@2
|
143 mrs->intra4x4_pred_mode_cache[3+8*1]=
|
|
nengel@2
|
144 mrs->intra4x4_pred_mode_cache[3+8*2]=
|
|
nengel@2
|
145 mrs->intra4x4_pred_mode_cache[3+8*3]=
|
|
nengel@2
|
146 mrs->intra4x4_pred_mode_cache[3+8*4]= 2 - 3*!(left_type & type_mask);
|
|
nengel@2
|
147 }
|
|
nengel@2
|
148 }
|
|
nengel@2
|
149 }
|
|
nengel@2
|
150 }
|
|
nengel@2
|
151
|
|
nengel@2
|
152 if(IS_INTER(mb_type) ||(IS_DIRECT(mb_type) && s->direct_spatial_mv_pred)){
|
|
nengel@2
|
153 int list;
|
|
nengel@2
|
154
|
|
nengel@2
|
155 // memset(mrs->mv_cache, 0, sizeof(mrs->mv_cache));
|
|
nengel@2
|
156 // memset(mrs->ref_cache, 0, sizeof(mrs->ref_cache));
|
|
nengel@2
|
157
|
|
nengel@2
|
158 mrs->ref_cache[0][scan8[5 ]+1] = mrs->ref_cache[0][scan8[7 ]+1] = mrs->ref_cache[0][scan8[13]+1] =
|
|
nengel@2
|
159 mrs->ref_cache[1][scan8[5 ]+1] = mrs->ref_cache[1][scan8[7 ]+1] = mrs->ref_cache[1][scan8[13]+1] = PART_NOT_AVAILABLE;
|
|
nengel@2
|
160
|
|
nengel@2
|
161 for(list=0; list<s->list_count; list++){
|
|
nengel@2
|
162 if(!USES_LIST(mb_type, list)){
|
|
nengel@2
|
163 continue;
|
|
nengel@2
|
164 }
|
|
nengel@2
|
165 assert(!(IS_DIRECT(mb_type) && !s->direct_spatial_mv_pred));
|
|
nengel@2
|
166
|
|
nengel@2
|
167 if(USES_LIST(top_type, list)){
|
|
nengel@2
|
168 const int b_xy= 4*mb_x + 3*mrc->b_stride;
|
|
nengel@2
|
169 AV_COPY128(mrs->mv_cache[list][scan8[0] + 0 - 1*8], mrs->motion_val_top[list][b_xy + 0]);
|
|
nengel@2
|
170 mrs->ref_cache[list][scan8[0] + 0 - 1*8]=
|
|
nengel@2
|
171 mrs->ref_cache[list][scan8[0] + 1 - 1*8]= mrs->ref_index_top[list][4*mb_x + 2];
|
|
nengel@2
|
172 mrs->ref_cache[list][scan8[0] + 2 - 1*8]=
|
|
nengel@2
|
173 mrs->ref_cache[list][scan8[0] + 3 - 1*8]= mrs->ref_index_top[list][4*mb_x + 3];
|
|
nengel@2
|
174 }else{
|
|
nengel@2
|
175 AV_ZERO128(mrs->mv_cache[list][scan8[0] + 0 - 1*8]);
|
|
nengel@2
|
176 AV_WN32A(&mrs->ref_cache[list][scan8[0] + 0 - 1*8], ((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE)&0xFF)*0x01010101);
|
|
nengel@2
|
177 }
|
|
nengel@2
|
178
|
|
nengel@2
|
179 if(mb_type & (MB_TYPE_16x8|MB_TYPE_8x8)){
|
|
nengel@2
|
180 for(i=0; i<2; i++){
|
|
nengel@2
|
181 int cache_idx = scan8[0] - 1 + i*2*8;
|
|
nengel@2
|
182 if(USES_LIST(left_type, list)){
|
|
nengel@2
|
183 const int b_xy= 4*(mb_x-1) + 3;
|
|
nengel@2
|
184 const int b8_x= 4*(mb_x-1) + 1;
|
|
nengel@2
|
185 AV_COPY32(mrs->mv_cache[list][cache_idx ], mrs->motion_val[list][b_xy + mrc->b_stride*left_block[0+i*2]]);
|
|
nengel@2
|
186 AV_COPY32(mrs->mv_cache[list][cache_idx+8], mrs->motion_val[list][b_xy + mrc->b_stride*left_block[1+i*2]]);
|
|
nengel@2
|
187 mrs->ref_cache[list][cache_idx ]= mrs->ref_index[list][b8_x + (left_block[0+i*2]&~1)];
|
|
nengel@2
|
188 mrs->ref_cache[list][cache_idx+8]= mrs->ref_index[list][b8_x + (left_block[1+i*2]&~1)];
|
|
nengel@2
|
189 }else{
|
|
nengel@2
|
190 AV_ZERO32(mrs->mv_cache [list][cache_idx ]);
|
|
nengel@2
|
191 AV_ZERO32(mrs->mv_cache [list][cache_idx+8]);
|
|
nengel@2
|
192 mrs->ref_cache[list][cache_idx ]=
|
|
nengel@2
|
193 mrs->ref_cache[list][cache_idx+8]= (left_type ? LIST_NOT_USED : PART_NOT_AVAILABLE);
|
|
nengel@2
|
194 }
|
|
nengel@2
|
195 }
|
|
nengel@2
|
196 }else{
|
|
nengel@2
|
197 if(USES_LIST(left_type, list)){
|
|
nengel@2
|
198 const int b_x = 4*(mb_x-1) + 3;
|
|
nengel@2
|
199 const int b8_x= 4*(mb_x-1) + 1;
|
|
nengel@2
|
200 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1], mrs->motion_val[list][b_x + mrc->b_stride*left_block[0]]);
|
|
nengel@2
|
201 mrs->ref_cache[list][scan8[0] - 1]= mrs->ref_index[list][b8_x + (left_block[0]&~1)];
|
|
nengel@2
|
202 }else{
|
|
nengel@2
|
203 AV_ZERO32(mrs->mv_cache [list][scan8[0] - 1]);
|
|
nengel@2
|
204 mrs->ref_cache[list][scan8[0] - 1]= left_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
|
|
nengel@2
|
205 }
|
|
nengel@2
|
206 }
|
|
nengel@2
|
207
|
|
nengel@2
|
208 if(USES_LIST(topright_type, list)){
|
|
nengel@2
|
209 const int b_xy= 4*(mb_x+1) + 3*mrc->b_stride;
|
|
nengel@2
|
210 AV_COPY32(mrs->mv_cache[list][scan8[0] + 4 - 1*8], mrs->motion_val_top[list][b_xy]);
|
|
nengel@2
|
211 mrs->ref_cache[list][scan8[0] + 4 - 1*8]= mrs->ref_index_top[list][4*(mb_x+1) + 2];
|
|
nengel@2
|
212 }else{
|
|
nengel@2
|
213 AV_ZERO32(mrs->mv_cache [list][scan8[0] + 4 - 1*8]);
|
|
nengel@2
|
214 mrs->ref_cache[list][scan8[0] + 4 - 1*8]= topright_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
|
|
nengel@2
|
215 }
|
|
nengel@2
|
216 if(mrs->ref_cache[list][scan8[0] + 4 - 1*8] < 0){
|
|
nengel@2
|
217 int topleft_partition= -1;
|
|
nengel@2
|
218 if(USES_LIST(topleft_type, list)){
|
|
nengel@2
|
219 const int b_xy = 4*(mb_x-1) + 3 + mrc->b_stride + (topleft_partition & 2*mrc->b_stride);
|
|
nengel@2
|
220 const int b8_x= 4*(mb_x-1) + 1 + (topleft_partition & 2);
|
|
nengel@2
|
221 AV_COPY32(mrs->mv_cache[list][scan8[0] - 1 - 1*8], mrs->motion_val_top[list][b_xy]);
|
|
nengel@2
|
222 mrs->ref_cache[list][scan8[0] - 1 - 1*8]= mrs->ref_index_top[list][b8_x];
|
|
nengel@2
|
223 }else{
|
|
nengel@2
|
224 AV_ZERO32(mrs->mv_cache[list][scan8[0] - 1 - 1*8]);
|
|
nengel@2
|
225 mrs->ref_cache[list][scan8[0] - 1 - 1*8]= topleft_type ? LIST_NOT_USED : PART_NOT_AVAILABLE;
|
|
nengel@2
|
226 }
|
|
nengel@2
|
227 }
|
|
nengel@2
|
228
|
|
nengel@2
|
229 if((mb_type&(MB_TYPE_SKIP|MB_TYPE_DIRECT2)))
|
|
nengel@2
|
230 continue;
|
|
nengel@2
|
231
|
|
nengel@2
|
232 if(!(mb_type&(MB_TYPE_SKIP|MB_TYPE_DIRECT2))) {
|
|
nengel@2
|
233 mrs->ref_cache[list][scan8[4 ]] =
|
|
nengel@2
|
234 mrs->ref_cache[list][scan8[12]] = PART_NOT_AVAILABLE;
|
|
nengel@2
|
235 AV_ZERO32(mrs->mv_cache [list][scan8[4 ]]);
|
|
nengel@2
|
236 AV_ZERO32(mrs->mv_cache [list][scan8[12]]);
|
|
nengel@2
|
237 }
|
|
nengel@2
|
238 }
|
|
nengel@2
|
239 }
|
|
nengel@2
|
240 }
|
|
nengel@2
|
241
|
|
nengel@2
|
242 static inline void write_back_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mb_type){
|
|
nengel@2
|
243 const int b_stride = mrc->b_stride;
|
|
nengel@2
|
244 const int b_x = 4*m->mb_x; //try mb2b(8)_xy
|
|
nengel@2
|
245 const int b8_x= 4*m->mb_x;
|
|
nengel@2
|
246 int list;
|
|
nengel@2
|
247
|
|
nengel@2
|
248 if(!USES_LIST(mb_type, 0))
|
|
nengel@2
|
249 fill_rectangle(&mrs->ref_index[0][b8_x], 2, 2, 2, (uint8_t)LIST_NOT_USED, 1);
|
|
nengel@2
|
250
|
|
nengel@2
|
251 for(list=0; list<s->list_count; list++){
|
|
nengel@2
|
252 int y;
|
|
nengel@2
|
253 int16_t (*mv_dst)[2];
|
|
nengel@2
|
254 int16_t (*mv_src)[2];
|
|
nengel@2
|
255
|
|
nengel@2
|
256 if(!USES_LIST(mb_type, list))
|
|
nengel@2
|
257 continue;
|
|
nengel@2
|
258
|
|
nengel@2
|
259 mv_dst = &mrs->motion_val[list][b_x];
|
|
nengel@2
|
260 mv_src = &mrs->mv_cache[list][scan8[0]];
|
|
nengel@2
|
261 for(y=0; y<4; y++){
|
|
nengel@2
|
262 AV_COPY128(mv_dst + y*b_stride, mv_src + 8*y);
|
|
nengel@2
|
263 }
|
|
nengel@2
|
264
|
|
nengel@2
|
265 {
|
|
nengel@2
|
266 int8_t *ref_index = &mrs->ref_index[list][b8_x];
|
|
nengel@2
|
267 ref_index[0+0*2]= mrs->ref_cache[list][scan8[0]];
|
|
nengel@2
|
268 ref_index[1+0*2]= mrs->ref_cache[list][scan8[4]];
|
|
nengel@2
|
269 ref_index[0+1*2]= mrs->ref_cache[list][scan8[8]];
|
|
nengel@2
|
270 ref_index[1+1*2]= mrs->ref_cache[list][scan8[12]];
|
|
nengel@2
|
271 }
|
|
nengel@2
|
272 }
|
|
nengel@2
|
273 }
|
|
nengel@2
|
274
|
|
nengel@2
|
275
|
|
nengel@2
|
276 /**
|
|
nengel@2
|
277 * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
|
|
nengel@2
|
278 */
|
|
nengel@2
|
279 static int check_intra4x4_pred_mode(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m){
|
|
nengel@2
|
280 static const int8_t top [12]= {-1, 0,LEFT_DC_PRED,-1,-1,-1,-1,-1, 0};
|
|
nengel@2
|
281 static const int8_t left[12]= { 0,-1, TOP_DC_PRED, 0,-1,-1,-1, 0,-1,DC_128_PRED};
|
|
nengel@2
|
282 int i;
|
|
nengel@2
|
283
|
|
nengel@2
|
284 if(!(mrs->top_samples_available&0x8000)){
|
|
nengel@2
|
285 for(i=0; i<4; i++){
|
|
nengel@2
|
286 int status= top[ mrs->intra4x4_pred_mode_cache[scan8[0] + i] ];
|
|
nengel@2
|
287 if(status<0){
|
|
nengel@2
|
288 av_log(AV_LOG_ERROR, "top block unavailable for requested intra4x4 mode %d at %d %d\n", status, m->mb_x, m->mb_y);
|
|
nengel@2
|
289 return -1;
|
|
nengel@2
|
290 } else if(status){
|
|
nengel@2
|
291 mrs->intra4x4_pred_mode_cache[scan8[0] + i]= status;
|
|
nengel@2
|
292 }
|
|
nengel@2
|
293 }
|
|
nengel@2
|
294 }
|
|
nengel@2
|
295
|
|
nengel@2
|
296 if((mrs->left_samples_available&0x8888)!=0x8888){
|
|
nengel@2
|
297 static const int mask[4]={0x8000,0x2000,0x80,0x20};
|
|
nengel@2
|
298 for(i=0; i<4; i++){
|
|
nengel@2
|
299 if(!(mrs->left_samples_available&mask[i])){
|
|
nengel@2
|
300 int status= left[ mrs->intra4x4_pred_mode_cache[scan8[0] + 8*i] ];
|
|
nengel@2
|
301 if(status<0){
|
|
nengel@2
|
302 av_log(AV_LOG_ERROR, "left block unavailable for requested intra4x4 mode %d at %d %d\n", status, m->mb_x, m->mb_y);
|
|
nengel@2
|
303 return -1;
|
|
nengel@2
|
304 } else if(status){
|
|
nengel@2
|
305 mrs->intra4x4_pred_mode_cache[scan8[0] + 8*i]= status;
|
|
nengel@2
|
306 }
|
|
nengel@2
|
307 }
|
|
nengel@2
|
308 }
|
|
nengel@2
|
309 }
|
|
nengel@2
|
310 return 0;
|
|
nengel@2
|
311 }
|
|
nengel@2
|
312
|
|
nengel@2
|
313 /**
|
|
nengel@2
|
314 * checks if the top & left blocks are available if needed & changes the dc mode so it only uses the available blocks.
|
|
nengel@2
|
315 */
|
|
nengel@2
|
316 static int check_intra_pred_mode(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int mode){
|
|
nengel@2
|
317 static const int8_t top [7]= {LEFT_DC_PRED8x8, 1,-1,-1};
|
|
nengel@2
|
318 static const int8_t left[7]= { TOP_DC_PRED8x8,-1, 2,-1,DC_128_PRED8x8};
|
|
nengel@2
|
319
|
|
nengel@2
|
320 if(mode > 6) {
|
|
nengel@2
|
321 av_log(AV_LOG_ERROR, "out of range intra chroma pred mode at %d %d\n", m->mb_x, m->mb_y);
|
|
nengel@2
|
322 return -1;
|
|
nengel@2
|
323 }
|
|
nengel@2
|
324
|
|
nengel@2
|
325 if(!(mrs->top_samples_available&0x8000)){
|
|
nengel@2
|
326 mode= top[ mode ];
|
|
nengel@2
|
327 if(mode<0){
|
|
nengel@2
|
328 av_log(AV_LOG_ERROR, "top block unavailable for requested intra mode at %d %d\n", m->mb_x, m->mb_y);
|
|
nengel@2
|
329 return -1;
|
|
nengel@2
|
330 }
|
|
nengel@2
|
331 }
|
|
nengel@2
|
332
|
|
nengel@2
|
333 if((mrs->left_samples_available&0x8080) != 0x8080){
|
|
nengel@2
|
334 mode= left[ mode ];
|
|
nengel@2
|
335 if(mrs->left_samples_available&0x8080){ //mad cow disease mode, aka MBAFF + constrained_intra_pred
|
|
nengel@2
|
336 mode= ALZHEIMER_DC_L0T_PRED8x8 + (!(mrs->left_samples_available&0x8000)) + 2*(mode == DC_128_PRED8x8);
|
|
nengel@2
|
337 }
|
|
nengel@2
|
338 if(mode<0){
|
|
nengel@2
|
339 av_log(AV_LOG_ERROR, "left block unavailable for requested intra mode at %d %d\n", m->mb_x, m->mb_y);
|
|
nengel@2
|
340 return -1;
|
|
nengel@2
|
341 }
|
|
nengel@2
|
342 }
|
|
nengel@2
|
343 return mode;
|
|
nengel@2
|
344 }
|
|
nengel@2
|
345
|
|
nengel@2
|
346 /**
|
|
nengel@2
|
347 * gets the predicted intra4x4 prediction mode.
|
|
nengel@2
|
348 */
|
|
nengel@2
|
349 static inline int pred_intra_mode(MBRecContext *mrc, MBRecState *mrs, int n){
|
|
nengel@2
|
350 const int index8= scan8[n];
|
|
nengel@2
|
351 const int left= mrs->intra4x4_pred_mode_cache[index8 - 1];
|
|
nengel@2
|
352 const int top = mrs->intra4x4_pred_mode_cache[index8 - 8];
|
|
nengel@2
|
353 const int min= FFMIN(left, top);
|
|
nengel@2
|
354
|
|
nengel@2
|
355 if(min<0) return DC_PRED;
|
|
nengel@2
|
356 else return min;
|
|
nengel@2
|
357 }
|
|
nengel@2
|
358
|
|
nengel@2
|
359 static void write_back_intra_pred_mode_rec(MBRecContext *mrc, MBRecState *mrs, H264Mb *m, int mb_x){
|
|
nengel@2
|
360 int8_t *mode= &mrs->intra4x4_pred_mode[4*mb_x];
|
|
nengel@2
|
361
|
|
nengel@2
|
362 AV_COPY32(mode, mrs->intra4x4_pred_mode_cache + 4 + 8*4);
|
|
nengel@2
|
363 #if OMPSS
|
|
nengel@2
|
364 if (m->mb_x < mrc->mb_width-1){
|
|
nengel@2
|
365 H264Mb *mr= m+1;
|
|
nengel@2
|
366 mode = mr->intra4x4_pred_mode_left;
|
|
nengel@2
|
367 mode[0]= mrs->intra4x4_pred_mode_cache[7+8*1];
|
|
nengel@2
|
368 mode[1]= mrs->intra4x4_pred_mode_cache[7+8*2];
|
|
nengel@2
|
369 mode[2]= mrs->intra4x4_pred_mode_cache[7+8*3];
|
|
nengel@2
|
370 mode[3]= mrs->intra4x4_pred_mode_cache[7+8*4];
|
|
nengel@2
|
371 }
|
|
nengel@2
|
372 #else
|
|
nengel@2
|
373 mode = mrs->intra4x4_pred_mode_left;
|
|
nengel@2
|
374 mode[0]= mrs->intra4x4_pred_mode_cache[7+8*1];
|
|
nengel@2
|
375 mode[1]= mrs->intra4x4_pred_mode_cache[7+8*2];
|
|
nengel@2
|
376 mode[2]= mrs->intra4x4_pred_mode_cache[7+8*3];
|
|
nengel@2
|
377 mode[3]= mrs->intra4x4_pred_mode_cache[7+8*4];
|
|
nengel@2
|
378 #endif
|
|
nengel@2
|
379 }
|
|
nengel@2
|
380
|
|
nengel@2
|
381 static void pred_spatial_direct_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int *mb_type){
|
|
nengel@2
|
382 int b4_stride = mrc->b_stride;
|
|
nengel@2
|
383 const int mb_x = m->mb_x;
|
|
nengel@2
|
384 int mb_type_col[2];
|
|
nengel@2
|
385 const int16_t (*l1mv0)[2], (*l1mv1)[2];
|
|
nengel@2
|
386 const int8_t *l1ref0, *l1ref1;
|
|
nengel@2
|
387 const int is_b8x8 = IS_8X8(*mb_type);
|
|
nengel@2
|
388 unsigned int sub_mb_type= MB_TYPE_L0L1;
|
|
nengel@2
|
389 int i8, i4;
|
|
nengel@2
|
390 int ref[2];
|
|
nengel@2
|
391 int mv[2];
|
|
nengel@2
|
392 int list;
|
|
nengel@2
|
393
|
|
nengel@2
|
394 //assert(h->ref_list[1][0].reference&3);
|
|
nengel@2
|
395
|
|
nengel@2
|
396 #define MB_TYPE_16x16_OR_INTRA (MB_TYPE_16x16|MB_TYPE_INTRA4x4|MB_TYPE_INTRA16x16|MB_TYPE_INTRA_PCM)
|
|
nengel@2
|
397
|
|
nengel@2
|
398 /* ref = min(neighbors) */
|
|
nengel@2
|
399 for(list=0; list<2; list++){
|
|
nengel@2
|
400 int left_ref = mrs->ref_cache[list][scan8[0] - 1];
|
|
nengel@2
|
401 int top_ref = mrs->ref_cache[list][scan8[0] - 8];
|
|
nengel@2
|
402 int refc = mrs->ref_cache[list][scan8[0] - 8 + 4];
|
|
nengel@2
|
403 const int16_t *C= mrs->mv_cache[list][ scan8[0] - 8 + 4];
|
|
nengel@2
|
404 if(refc == PART_NOT_AVAILABLE){
|
|
nengel@2
|
405 refc = mrs->ref_cache[list][scan8[0] - 8 - 1];
|
|
nengel@2
|
406 C = mrs->mv_cache[list][scan8[0] - 8 - 1];
|
|
nengel@2
|
407 }
|
|
nengel@2
|
408 ref[list] = FFMIN3((unsigned)left_ref, (unsigned)top_ref, (unsigned)refc);
|
|
nengel@2
|
409 if(ref[list] >= 0){
|
|
nengel@2
|
410 //this is just pred_motion() but with the cases removed that cannot happen for direct blocks
|
|
nengel@2
|
411 const int16_t * const A= mrs->mv_cache[list][ scan8[0] - 1 ];
|
|
nengel@2
|
412 const int16_t * const B= mrs->mv_cache[list][ scan8[0] - 8 ];
|
|
nengel@2
|
413
|
|
nengel@2
|
414 int match_count= (left_ref==ref[list]) + (top_ref==ref[list]) + (refc==ref[list]);
|
|
nengel@2
|
415 if(match_count > 1){ //most common
|
|
nengel@2
|
416 mv[list]= pack16to32(mid_pred(A[0], B[0], C[0]),
|
|
nengel@2
|
417 mid_pred(A[1], B[1], C[1]) );
|
|
nengel@2
|
418 }else {
|
|
nengel@2
|
419 assert(match_count==1);
|
|
nengel@2
|
420 if(left_ref==ref[list]){
|
|
nengel@2
|
421 mv[list]= AV_RN32A(A);
|
|
nengel@2
|
422 }else if(top_ref==ref[list]){
|
|
nengel@2
|
423 mv[list]= AV_RN32A(B);
|
|
nengel@2
|
424 }else{
|
|
nengel@2
|
425 mv[list]= AV_RN32A(C);
|
|
nengel@2
|
426 }
|
|
nengel@2
|
427 }
|
|
nengel@2
|
428 }else{
|
|
nengel@2
|
429 int mask= ~(MB_TYPE_L0 << (2*list));
|
|
nengel@2
|
430 mv[list] = 0;
|
|
nengel@2
|
431 ref[list] = -1;
|
|
nengel@2
|
432 if(!is_b8x8)
|
|
nengel@2
|
433 *mb_type &= mask;
|
|
nengel@2
|
434 sub_mb_type &= mask;
|
|
nengel@2
|
435 }
|
|
nengel@2
|
436 }
|
|
nengel@2
|
437
|
|
nengel@2
|
438 if(ref[0] < 0 && ref[1] < 0){
|
|
nengel@2
|
439 ref[0] = ref[1] = 0;
|
|
nengel@2
|
440 if(!is_b8x8)
|
|
nengel@2
|
441 *mb_type |= MB_TYPE_L0L1;
|
|
nengel@2
|
442 sub_mb_type |= MB_TYPE_L0L1;
|
|
nengel@2
|
443 }
|
|
nengel@2
|
444
|
|
nengel@2
|
445 if(!(is_b8x8|mv[0]|mv[1])){
|
|
nengel@2
|
446 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1);
|
|
nengel@2
|
447 fill_rectangle(&mrs->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1);
|
|
nengel@2
|
448 fill_rectangle(&mrs->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4);
|
|
nengel@2
|
449 fill_rectangle(&mrs->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4);
|
|
nengel@2
|
450 *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;
|
|
nengel@2
|
451 return;
|
|
nengel@2
|
452 }
|
|
nengel@2
|
453
|
|
nengel@2
|
454 mb_type_col[0] =
|
|
nengel@2
|
455 mb_type_col[1] = mrs->list1_mb_type[mb_x];
|
|
nengel@2
|
456
|
|
nengel@2
|
457 sub_mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
|
nengel@2
|
458 if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){
|
|
nengel@2
|
459 *mb_type |= MB_TYPE_16x16|MB_TYPE_DIRECT2; /* B_16x16 */
|
|
nengel@2
|
460 }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){
|
|
nengel@2
|
461 *mb_type |= MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));
|
|
nengel@2
|
462 }else{
|
|
nengel@2
|
463 if(!s->direct_8x8_inference_flag){
|
|
nengel@2
|
464 /* FIXME save sub mb types from previous frames (or derive from MVs)
|
|
nengel@2
|
465 * so we know exactly what block size to use */
|
|
nengel@2
|
466 sub_mb_type += (MB_TYPE_8x8-MB_TYPE_16x16); /* B_SUB_4x4 */
|
|
nengel@2
|
467 }
|
|
nengel@2
|
468 *mb_type |= MB_TYPE_8x8;
|
|
nengel@2
|
469 }
|
|
nengel@2
|
470
|
|
nengel@2
|
471 l1mv0 = (void *) &mrs->list1_motion_val[0][4*mb_x];
|
|
nengel@2
|
472 l1mv1 = (void *) &mrs->list1_motion_val[1][4*mb_x];
|
|
nengel@2
|
473 l1ref0 = &mrs->list1_ref_index [0][4*mb_x];
|
|
nengel@2
|
474 l1ref1 = &mrs->list1_ref_index [1][4*mb_x];
|
|
nengel@2
|
475 // if(!b8_stride){
|
|
nengel@2
|
476 // if(m->mb_y&1){
|
|
nengel@2
|
477 // l1ref0 += 2;
|
|
nengel@2
|
478 // l1ref1 += 2;
|
|
nengel@2
|
479 // l1mv0 += 2*b4_stride;
|
|
nengel@2
|
480 // l1mv1 += 2*b4_stride;
|
|
nengel@2
|
481 // }
|
|
nengel@2
|
482 // }
|
|
nengel@2
|
483
|
|
nengel@2
|
484 if(IS_16X16(*mb_type)){
|
|
nengel@2
|
485 int a,b;
|
|
nengel@2
|
486
|
|
nengel@2
|
487 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, (uint8_t)ref[0], 1);
|
|
nengel@2
|
488 fill_rectangle(&mrs->ref_cache[1][scan8[0]], 4, 4, 8, (uint8_t)ref[1], 1);
|
|
nengel@2
|
489 if(!IS_INTRA(mb_type_col[0]) && ( (l1ref0[0] == 0 && FFABS(l1mv0[0][0]) <= 1 && FFABS(l1mv0[0][1]) <= 1)
|
|
nengel@2
|
490 || (l1ref0[0] < 0 && l1ref1[0] == 0 && FFABS(l1mv1[0][0]) <= 1 && FFABS(l1mv1[0][1]) <= 1
|
|
nengel@2
|
491 ))){
|
|
nengel@2
|
492 a=b=0;
|
|
nengel@2
|
493 if(ref[0] > 0)
|
|
nengel@2
|
494 a= mv[0];
|
|
nengel@2
|
495 if(ref[1] > 0)
|
|
nengel@2
|
496 b= mv[1];
|
|
nengel@2
|
497 }else{
|
|
nengel@2
|
498 a= mv[0];
|
|
nengel@2
|
499 b= mv[1];
|
|
nengel@2
|
500 }
|
|
nengel@2
|
501 fill_rectangle(&mrs->mv_cache[0][scan8[0]], 4, 4, 8, a, 4);
|
|
nengel@2
|
502 fill_rectangle(&mrs->mv_cache[1][scan8[0]], 4, 4, 8, b, 4);
|
|
nengel@2
|
503 }else{
|
|
nengel@2
|
504 int n=0;
|
|
nengel@2
|
505 for(i8=0; i8<4; i8++){
|
|
nengel@2
|
506 const int x8 = i8&1;
|
|
nengel@2
|
507 const int y8 = i8>>1;
|
|
nengel@2
|
508
|
|
nengel@2
|
509 if(is_b8x8 && !IS_DIRECT(m->sub_mb_type[i8]))
|
|
nengel@2
|
510 continue;
|
|
nengel@2
|
511 m->sub_mb_type[i8] = sub_mb_type;
|
|
nengel@2
|
512
|
|
nengel@2
|
513 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, mv[0], 4);
|
|
nengel@2
|
514 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, mv[1], 4);
|
|
nengel@2
|
515 fill_rectangle(&mrs->ref_cache[0][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[0], 1);
|
|
nengel@2
|
516 fill_rectangle(&mrs->ref_cache[1][scan8[i8*4]], 2, 2, 8, (uint8_t)ref[1], 1);
|
|
nengel@2
|
517
|
|
nengel@2
|
518 /* col_zero_flag */
|
|
nengel@2
|
519 if(!IS_INTRA(mb_type_col[0]) && (l1ref0[i8] == 0 || (l1ref0[i8] < 0 && l1ref1[i8] == 0 ))
|
|
nengel@2
|
520 ){
|
|
nengel@2
|
521 const int16_t (*l1mv)[2]= l1ref0[i8] == 0 ? l1mv0 : l1mv1;
|
|
nengel@2
|
522 if(IS_SUB_8X8(sub_mb_type)){
|
|
nengel@2
|
523 const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride];
|
|
nengel@2
|
524 if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){
|
|
nengel@2
|
525 if(ref[0] == 0)
|
|
nengel@2
|
526 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);
|
|
nengel@2
|
527 if(ref[1] == 0)
|
|
nengel@2
|
528 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);
|
|
nengel@2
|
529 n+=4;
|
|
nengel@2
|
530 }
|
|
nengel@2
|
531 }else{
|
|
nengel@2
|
532 int k=0;
|
|
nengel@2
|
533 for(i4=0; i4<4; i4++){
|
|
nengel@2
|
534 const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride];
|
|
nengel@2
|
535 if(FFABS(mv_col[0]) <= 1 && FFABS(mv_col[1]) <= 1){
|
|
nengel@2
|
536 if(ref[0] == 0)
|
|
nengel@2
|
537 AV_ZERO32(mrs->mv_cache[0][scan8[i8*4+i4]]);
|
|
nengel@2
|
538 if(ref[1] == 0)
|
|
nengel@2
|
539 AV_ZERO32(mrs->mv_cache[1][scan8[i8*4+i4]]);
|
|
nengel@2
|
540 k++;
|
|
nengel@2
|
541 }
|
|
nengel@2
|
542 }
|
|
nengel@2
|
543 if(!(k&3))
|
|
nengel@2
|
544 m->sub_mb_type[i8]+= MB_TYPE_16x16 - MB_TYPE_8x8;
|
|
nengel@2
|
545 n+=k;
|
|
nengel@2
|
546 }
|
|
nengel@2
|
547 }
|
|
nengel@2
|
548 }
|
|
nengel@2
|
549 if(!is_b8x8 && !(n&15)){
|
|
nengel@2
|
550 *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;
|
|
nengel@2
|
551 }
|
|
nengel@2
|
552 }
|
|
nengel@2
|
553 }
|
|
nengel@2
|
554
|
|
nengel@2
|
555 static void pred_temp_direct_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int *mb_type){
|
|
nengel@2
|
556 const int mb_x = m->mb_x;
|
|
nengel@2
|
557 int b4_stride = mrc->b_stride;
|
|
nengel@2
|
558 int mb_type_col[2];
|
|
nengel@2
|
559 const int16_t (*l1mv0)[2], (*l1mv1)[2];
|
|
nengel@2
|
560 const int8_t *l1ref0, *l1ref1;
|
|
nengel@2
|
561 const int is_b8x8 = IS_8X8(*mb_type);
|
|
nengel@2
|
562 unsigned int sub_mb_type;
|
|
nengel@2
|
563 int i8, i4;
|
|
nengel@2
|
564 const int *map_col_to_list0[2] = {s->map_col_to_list0[0], s->map_col_to_list0[1]};
|
|
nengel@2
|
565 const int *dist_scale_factor = s->dist_scale_factor;
|
|
nengel@2
|
566
|
|
nengel@2
|
567 mb_type_col[0] =
|
|
nengel@2
|
568 mb_type_col[1] = mrs->list1_mb_type[mb_x];
|
|
nengel@2
|
569
|
|
nengel@2
|
570 sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
|
nengel@2
|
571 if(!is_b8x8 && (mb_type_col[0] & MB_TYPE_16x16_OR_INTRA)){
|
|
nengel@2
|
572 *mb_type |= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */
|
|
nengel@2
|
573 }else if(!is_b8x8 && (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16))){
|
|
nengel@2
|
574 *mb_type |= MB_TYPE_L0L1|MB_TYPE_DIRECT2 | (mb_type_col[0] & (MB_TYPE_16x8|MB_TYPE_8x16));
|
|
nengel@2
|
575 }else{
|
|
nengel@2
|
576 if(!s->direct_8x8_inference_flag){
|
|
nengel@2
|
577 /* FIXME save sub mb types from previous frames (or derive from MVs)
|
|
nengel@2
|
578 * so we know exactly what block size to use */
|
|
nengel@2
|
579 sub_mb_type = MB_TYPE_8x8|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_4x4 */
|
|
nengel@2
|
580 }
|
|
nengel@2
|
581 *mb_type |= MB_TYPE_8x8|MB_TYPE_L0L1;
|
|
nengel@2
|
582 }
|
|
nengel@2
|
583
|
|
nengel@2
|
584 l1mv0 = (void *) &mrs->list1_motion_val[0][4*mb_x];
|
|
nengel@2
|
585 l1mv1 = (void *) &mrs->list1_motion_val[1][4*mb_x];
|
|
nengel@2
|
586 l1ref0 = &mrs->list1_ref_index [0][4*mb_x];
|
|
nengel@2
|
587 l1ref1 = &mrs->list1_ref_index [1][4*mb_x];
|
|
nengel@2
|
588
|
|
nengel@2
|
589 /* one-to-one mv scaling */
|
|
nengel@2
|
590 if(IS_16X16(*mb_type)){
|
|
nengel@2
|
591 int ref, mv0, mv1;
|
|
nengel@2
|
592
|
|
nengel@2
|
593 fill_rectangle(&mrs->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1);
|
|
nengel@2
|
594 if(IS_INTRA(mb_type_col[0])){
|
|
nengel@2
|
595 ref=mv0=mv1=0;
|
|
nengel@2
|
596 }else{
|
|
nengel@2
|
597 const int ref0 = l1ref0[0] >= 0 ? map_col_to_list0[0][l1ref0[0]]
|
|
nengel@2
|
598 : map_col_to_list0[1][l1ref1[0]];
|
|
nengel@2
|
599 const int scale = dist_scale_factor[ref0];
|
|
nengel@2
|
600 const int16_t *mv_col = l1ref0[0] >= 0 ? l1mv0[0] : l1mv1[0];
|
|
nengel@2
|
601 int mv_l0[2];
|
|
nengel@2
|
602 mv_l0[0] = (scale * mv_col[0] + 128) >> 8;
|
|
nengel@2
|
603 mv_l0[1] = (scale * mv_col[1] + 128) >> 8;
|
|
nengel@2
|
604 ref= ref0;
|
|
nengel@2
|
605 mv0= pack16to32(mv_l0[0],mv_l0[1]);
|
|
nengel@2
|
606 mv1= pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]);
|
|
nengel@2
|
607 }
|
|
nengel@2
|
608 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
|
|
nengel@2
|
609 fill_rectangle(&mrs->mv_cache[0][scan8[0]], 4, 4, 8, mv0, 4);
|
|
nengel@2
|
610 fill_rectangle(&mrs->mv_cache[1][scan8[0]], 4, 4, 8, mv1, 4);
|
|
nengel@2
|
611 }else{
|
|
nengel@2
|
612 for(i8=0; i8<4; i8++){
|
|
nengel@2
|
613 const int x8 = i8&1;
|
|
nengel@2
|
614 const int y8 = i8>>1;
|
|
nengel@2
|
615 int ref0, scale;
|
|
nengel@2
|
616 const int16_t (*l1mv)[2]= l1mv0;
|
|
nengel@2
|
617
|
|
nengel@2
|
618 if(is_b8x8 && !IS_DIRECT(m->sub_mb_type[i8]))
|
|
nengel@2
|
619 continue;
|
|
nengel@2
|
620 m->sub_mb_type[i8] = sub_mb_type;
|
|
nengel@2
|
621 fill_rectangle(&mrs->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1);
|
|
nengel@2
|
622 if(IS_INTRA(mb_type_col[0])){
|
|
nengel@2
|
623 fill_rectangle(&mrs->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1);
|
|
nengel@2
|
624 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);
|
|
nengel@2
|
625 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);
|
|
nengel@2
|
626 continue;
|
|
nengel@2
|
627 }
|
|
nengel@2
|
628
|
|
nengel@2
|
629 ref0 = l1ref0[i8];
|
|
nengel@2
|
630 if(ref0 >= 0)
|
|
nengel@2
|
631 ref0 = map_col_to_list0[0][ref0 ];
|
|
nengel@2
|
632 else{
|
|
nengel@2
|
633 ref0 = map_col_to_list0[1][l1ref1[i8]];
|
|
nengel@2
|
634 l1mv= l1mv1;
|
|
nengel@2
|
635 }
|
|
nengel@2
|
636 scale = dist_scale_factor[ref0];
|
|
nengel@2
|
637
|
|
nengel@2
|
638 fill_rectangle(&mrs->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1);
|
|
nengel@2
|
639 if(IS_SUB_8X8(sub_mb_type)){
|
|
nengel@2
|
640 const int16_t *mv_col = l1mv[x8*3 + y8*3*b4_stride];
|
|
nengel@2
|
641 int mx = (scale * mv_col[0] + 128) >> 8;
|
|
nengel@2
|
642 int my = (scale * mv_col[1] + 128) >> 8;
|
|
nengel@2
|
643 fill_rectangle(&mrs->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mx,my), 4);
|
|
nengel@2
|
644 fill_rectangle(&mrs->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mx-mv_col[0],my-mv_col[1]), 4);
|
|
nengel@2
|
645 }else
|
|
nengel@2
|
646 for(i4=0; i4<4; i4++){
|
|
nengel@2
|
647 const int16_t *mv_col = l1mv[x8*2 + (i4&1) + (y8*2 + (i4>>1))*b4_stride];
|
|
nengel@2
|
648 int16_t *mv_l0 = mrs->mv_cache[0][scan8[i8*4+i4]];
|
|
nengel@2
|
649 mv_l0[0] = (scale * mv_col[0] + 128) >> 8;
|
|
nengel@2
|
650 mv_l0[1] = (scale * mv_col[1] + 128) >> 8;
|
|
nengel@2
|
651 AV_WN32A(mrs->mv_cache[1][scan8[i8*4+i4]],
|
|
nengel@2
|
652 pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]));
|
|
nengel@2
|
653 }
|
|
nengel@2
|
654 }
|
|
nengel@2
|
655 }
|
|
nengel@2
|
656 }
|
|
nengel@2
|
657
|
|
nengel@2
|
658 void ff_h264_pred_direct_motion_rec(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m, int *mb_type){
|
|
nengel@2
|
659 if(s->direct_spatial_mv_pred){
|
|
nengel@2
|
660 pred_spatial_direct_motion_rec(mrc, mrs, s, m, mb_type);
|
|
nengel@2
|
661 }else{
|
|
nengel@2
|
662 pred_temp_direct_motion_rec(mrc, mrs, s, m, mb_type);
|
|
nengel@2
|
663 }
|
|
nengel@2
|
664 }
|
|
nengel@2
|
665
|
|
nengel@2
|
666 static inline int fetch_diagonal_mv(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, const int16_t **C, int i, int list, int part_width){
|
|
nengel@2
|
667 const int topright_ref= mrs->ref_cache[list][ i - 8 + part_width ];
|
|
nengel@2
|
668
|
|
nengel@2
|
669 if(topright_ref != PART_NOT_AVAILABLE){
|
|
nengel@2
|
670 *C= mrs->mv_cache[list][ i - 8 + part_width ];
|
|
nengel@2
|
671 return topright_ref;
|
|
nengel@2
|
672 }else{
|
|
nengel@2
|
673 *C= mrs->mv_cache[list][ i - 8 - 1 ];
|
|
nengel@2
|
674 return mrs->ref_cache[list][ i - 8 - 1 ];
|
|
nengel@2
|
675 }
|
|
nengel@2
|
676 }
|
|
nengel@2
|
677
|
|
nengel@2
|
678 /**
|
|
nengel@2
|
679 * gets the predicted MV.
|
|
nengel@2
|
680 * @param n the block index
|
|
nengel@2
|
681 * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4)
|
|
nengel@2
|
682 * @param mx the x component of the predicted motion vector
|
|
nengel@2
|
683 * @param my the y component of the predicted motion vector
|
|
nengel@2
|
684 */
|
|
nengel@2
|
685 static inline void pred_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, int n, int part_width, int list, int ref, int * const mx, int * const my){
|
|
nengel@2
|
686 const int index8= scan8[n];
|
|
nengel@2
|
687 const int top_ref= mrs->ref_cache[list][ index8 - 8 ];
|
|
nengel@2
|
688 const int left_ref= mrs->ref_cache[list][ index8 - 1 ];
|
|
nengel@2
|
689 const int16_t * const A= mrs->mv_cache[list][ index8 - 1 ];
|
|
nengel@2
|
690 const int16_t * const B= mrs->mv_cache[list][ index8 - 8 ];
|
|
nengel@2
|
691 const int16_t * C;
|
|
nengel@2
|
692 int diagonal_ref, match_count;
|
|
nengel@2
|
693
|
|
nengel@2
|
694 assert(part_width==1 || part_width==2 || part_width==4);
|
|
nengel@2
|
695
|
|
nengel@2
|
696 /* mv_cache
|
|
nengel@2
|
697 B . . A T T T T
|
|
nengel@2
|
698 U . . L . . , .
|
|
nengel@2
|
699 U . . L . . . .
|
|
nengel@2
|
700 U . . L . . , .
|
|
nengel@2
|
701 . . . L . . . .
|
|
nengel@2
|
702 */
|
|
nengel@2
|
703
|
|
nengel@2
|
704 diagonal_ref= fetch_diagonal_mv(mrc, mrs, s, &C, index8, list, part_width);
|
|
nengel@2
|
705 match_count= (diagonal_ref==ref) + (top_ref==ref) + (left_ref==ref);
|
|
nengel@2
|
706
|
|
nengel@2
|
707 if(match_count > 1){ //most common
|
|
nengel@2
|
708 *mx= mid_pred(A[0], B[0], C[0]);
|
|
nengel@2
|
709 *my= mid_pred(A[1], B[1], C[1]);
|
|
nengel@2
|
710 }else if(match_count==1){
|
|
nengel@2
|
711 if(left_ref==ref){
|
|
nengel@2
|
712 *mx= A[0];
|
|
nengel@2
|
713 *my= A[1];
|
|
nengel@2
|
714 }else if(top_ref==ref){
|
|
nengel@2
|
715 *mx= B[0];
|
|
nengel@2
|
716 *my= B[1];
|
|
nengel@2
|
717 }else{
|
|
nengel@2
|
718 *mx= C[0];
|
|
nengel@2
|
719 *my= C[1];
|
|
nengel@2
|
720 }
|
|
nengel@2
|
721 }else{
|
|
nengel@2
|
722 if(top_ref == PART_NOT_AVAILABLE && diagonal_ref == PART_NOT_AVAILABLE && left_ref != PART_NOT_AVAILABLE){
|
|
nengel@2
|
723 *mx= A[0];
|
|
nengel@2
|
724 *my= A[1];
|
|
nengel@2
|
725 }else{
|
|
nengel@2
|
726 *mx= mid_pred(A[0], B[0], C[0]);
|
|
nengel@2
|
727 *my= mid_pred(A[1], B[1], C[1]);
|
|
nengel@2
|
728 }
|
|
nengel@2
|
729 }
|
|
nengel@2
|
730
|
|
nengel@2
|
731 }
|
|
nengel@2
|
732
|
|
nengel@2
|
733 /**
|
|
nengel@2
|
734 * gets the directionally predicted 16x8 MV.
|
|
nengel@2
|
735 * @param n the block index
|
|
nengel@2
|
736 * @param mx the x component of the predicted motion vector
|
|
nengel@2
|
737 * @param my the y component of the predicted motion vector
|
|
nengel@2
|
738 */
|
|
nengel@2
|
739 static inline void pred_16x8_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, int n, int list, int ref, int * const mx, int * const my){
|
|
nengel@2
|
740 if(n==0){
|
|
nengel@2
|
741 const int top_ref= mrs->ref_cache[list][ scan8[0] - 8 ];
|
|
nengel@2
|
742 const int16_t * const B= mrs->mv_cache[list][ scan8[0] - 8 ];
|
|
nengel@2
|
743
|
|
nengel@2
|
744 if(top_ref == ref){
|
|
nengel@2
|
745 *mx= B[0];
|
|
nengel@2
|
746 *my= B[1];
|
|
nengel@2
|
747 return;
|
|
nengel@2
|
748 }
|
|
nengel@2
|
749 }else{
|
|
nengel@2
|
750 const int left_ref= mrs->ref_cache[list][ scan8[8] - 1 ];
|
|
nengel@2
|
751 const int16_t * const A= mrs->mv_cache[list][ scan8[8] - 1 ];
|
|
nengel@2
|
752
|
|
nengel@2
|
753 if(left_ref == ref){
|
|
nengel@2
|
754 *mx= A[0];
|
|
nengel@2
|
755 *my= A[1];
|
|
nengel@2
|
756 return;
|
|
nengel@2
|
757 }
|
|
nengel@2
|
758 }
|
|
nengel@2
|
759
|
|
nengel@2
|
760 //RARE
|
|
nengel@2
|
761 pred_motion(mrc, mrs, s, n, 4, list, ref, mx, my);
|
|
nengel@2
|
762 }
|
|
nengel@2
|
763
|
|
nengel@2
|
764 /**
|
|
nengel@2
|
765 * gets the directionally predicted 8x16 MV.
|
|
nengel@2
|
766 * @param n the block index
|
|
nengel@2
|
767 * @param mx the x component of the predicted motion vector
|
|
nengel@2
|
768 * @param my the y component of the predicted motion vector
|
|
nengel@2
|
769 */
|
|
nengel@2
|
770 static inline void pred_8x16_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, int n, int list, int ref, int * const mx, int * const my){
|
|
nengel@2
|
771 if(n==0){
|
|
nengel@2
|
772 const int left_ref= mrs->ref_cache[list][ scan8[0] - 1 ];
|
|
nengel@2
|
773 const int16_t * const A= mrs->mv_cache[list][ scan8[0] - 1 ];
|
|
nengel@2
|
774
|
|
nengel@2
|
775 if(left_ref == ref){
|
|
nengel@2
|
776 *mx= A[0];
|
|
nengel@2
|
777 *my= A[1];
|
|
nengel@2
|
778 return;
|
|
nengel@2
|
779 }
|
|
nengel@2
|
780 }else{
|
|
nengel@2
|
781 const int16_t * C;
|
|
nengel@2
|
782 int diagonal_ref;
|
|
nengel@2
|
783
|
|
nengel@2
|
784 diagonal_ref= fetch_diagonal_mv(mrc, mrs, s, &C, scan8[4], list, 2);
|
|
nengel@2
|
785 if(diagonal_ref == ref){
|
|
nengel@2
|
786 *mx= C[0];
|
|
nengel@2
|
787 *my= C[1];
|
|
nengel@2
|
788 return;
|
|
nengel@2
|
789 }
|
|
nengel@2
|
790 }
|
|
nengel@2
|
791
|
|
nengel@2
|
792 //RARE
|
|
nengel@2
|
793 pred_motion(mrc, mrs, s, n, 2, list, ref, mx, my);
|
|
nengel@2
|
794 }
|
|
nengel@2
|
795
|
|
nengel@2
|
796 static inline void pred_pskip_motion(MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb * m, int * const mx, int * const my){
|
|
nengel@2
|
797 const int top_ref = mrs->ref_cache[0][ scan8[0] - 8 ];
|
|
nengel@2
|
798 const int left_ref= mrs->ref_cache[0][ scan8[0] - 1 ];
|
|
nengel@2
|
799
|
|
nengel@2
|
800 if(top_ref == PART_NOT_AVAILABLE || left_ref == PART_NOT_AVAILABLE
|
|
nengel@2
|
801 || !( top_ref | AV_RN32A(mrs->mv_cache[0][ scan8[0] - 8 ]))
|
|
nengel@2
|
802 || !(left_ref | AV_RN32A(mrs->mv_cache[0][ scan8[0] - 1 ]))){
|
|
nengel@2
|
803
|
|
nengel@2
|
804 *mx = *my = 0;
|
|
nengel@2
|
805 return;
|
|
nengel@2
|
806 }
|
|
nengel@2
|
807
|
|
nengel@2
|
808 pred_motion(mrc, mrs, s, 0, 4, 0, 0, mx, my);
|
|
nengel@2
|
809
|
|
nengel@2
|
810 return;
|
|
nengel@2
|
811 }
|
|
nengel@2
|
812
|
|
nengel@2
|
813 #define ADD_MVD(list) \
|
|
nengel@2
|
814 { \
|
|
nengel@2
|
815 mx += m->mvd[list][mp][0]; \
|
|
nengel@2
|
816 my += m->mvd[list][mp][1]; \
|
|
nengel@2
|
817 mp++; \
|
|
nengel@2
|
818 }
|
|
nengel@2
|
819
|
|
nengel@2
|
820 int pred_motion_mb_rec (MBRecContext *mrc, MBRecState *mrs, H264Slice *s, H264Mb *m){
|
|
nengel@2
|
821 int mp=0;
|
|
nengel@2
|
822 int mb_type = m->mb_type;
|
|
nengel@2
|
823 const int mb_x = m->mb_x;
|
|
nengel@2
|
824
|
|
nengel@2
|
825 // mrc->m =m;
|
|
nengel@2
|
826
|
|
nengel@2
|
827 fill_decode_caches_rec(mrc, mrs, s, m, mb_type);
|
|
nengel@2
|
828 if (IS_SKIP(mb_type)){
|
|
nengel@2
|
829 mb_type=0;
|
|
nengel@2
|
830
|
|
nengel@2
|
831 if( s->slice_type_nos == FF_B_TYPE )
|
|
nengel@2
|
832 {
|
|
nengel@2
|
833 mb_type|= MB_TYPE_L0L1|MB_TYPE_DIRECT2|MB_TYPE_SKIP;
|
|
nengel@2
|
834 ff_h264_pred_direct_motion_rec(mrc, mrs, s, m, &mb_type);
|
|
nengel@2
|
835 }
|
|
nengel@2
|
836 else
|
|
nengel@2
|
837 {
|
|
nengel@2
|
838 int mx, my;
|
|
nengel@2
|
839
|
|
nengel@2
|
840 mb_type|= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0|MB_TYPE_SKIP; //FIXME check required
|
|
nengel@2
|
841 pred_pskip_motion(mrc, mrs, s, m, &mx, &my);
|
|
nengel@2
|
842 fill_rectangle(&mrs->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
|
|
nengel@2
|
843 fill_rectangle(mrs->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx,my), 4);
|
|
nengel@2
|
844 }
|
|
nengel@2
|
845
|
|
nengel@2
|
846 write_back_motion_rec(mrc, mrs, s, m, mb_type);
|
|
nengel@2
|
847 m->mb_type = mrs->mb_type[mb_x]= mb_type;
|
|
nengel@2
|
848 return 0;
|
|
nengel@2
|
849 }
|
|
nengel@2
|
850
|
|
nengel@2
|
851
|
|
nengel@2
|
852 if (IS_INTRA_PCM(mb_type)){
|
|
nengel@2
|
853 mrs->mb_type[mb_x] = mb_type;
|
|
nengel@2
|
854 return 0;
|
|
nengel@2
|
855 }
|
|
nengel@2
|
856 else if (IS_INTRA(mb_type)){
|
|
nengel@2
|
857 int i, pred_mode;
|
|
nengel@2
|
858
|
|
nengel@2
|
859 if( IS_INTRA4x4( mb_type ) ) {
|
|
nengel@2
|
860 if ( IS_8x8DCT(mb_type) ) {
|
|
nengel@2
|
861 for( i = 0; i < 16; i+=4 ) {
|
|
nengel@2
|
862 int pred = pred_intra_mode(mrc, mrs, i );
|
|
nengel@2
|
863 int mode = m->intra4x4_pred_mode[i];
|
|
nengel@2
|
864
|
|
nengel@2
|
865 mode = mode < 0 ? pred : mode + ( mode >= pred );
|
|
nengel@2
|
866 fill_rectangle( &mrs->intra4x4_pred_mode_cache[ scan8[i] ], 2, 2, 8, mode, 1 );
|
|
nengel@2
|
867 }
|
|
nengel@2
|
868 } else {
|
|
nengel@2
|
869 for( i = 0; i < 16; i++ ) {
|
|
nengel@2
|
870 int pred = pred_intra_mode(mrc, mrs, i );
|
|
nengel@2
|
871 int mode = m->intra4x4_pred_mode[i];
|
|
nengel@2
|
872 mode = mode < 0 ? pred : mode + ( mode >= pred );
|
|
nengel@2
|
873 mrs->intra4x4_pred_mode_cache[ scan8[i] ] = mode;
|
|
nengel@2
|
874 }
|
|
nengel@2
|
875 }
|
|
nengel@2
|
876 write_back_intra_pred_mode_rec(mrc, mrs, m, mb_x);
|
|
nengel@2
|
877 if( check_intra4x4_pred_mode(mrc, mrs, s, m) < 0 ) return -1;
|
|
nengel@2
|
878 } else {
|
|
nengel@2
|
879 m->intra16x16_pred_mode= check_intra_pred_mode(mrc, mrs, s, m, m->intra16x16_pred_mode );
|
|
nengel@2
|
880 if( m->intra16x16_pred_mode < 0 ) return -1;
|
|
nengel@2
|
881 }
|
|
nengel@2
|
882
|
|
nengel@2
|
883 pred_mode = m->chroma_pred_mode;
|
|
nengel@2
|
884 pred_mode= check_intra_pred_mode( mrc, mrs, s, m, pred_mode );
|
|
nengel@2
|
885 if( pred_mode < 0 ) return -1;
|
|
nengel@2
|
886 m->chroma_pred_mode= pred_mode;
|
|
nengel@2
|
887
|
|
nengel@2
|
888 }
|
|
nengel@2
|
889 else if (IS_8X8(mb_type)){
|
|
nengel@2
|
890 int i, j, list;
|
|
nengel@2
|
891
|
|
nengel@2
|
892 if( s->slice_type_nos == FF_B_TYPE ) {
|
|
nengel@2
|
893 if( IS_DIRECT(m->sub_mb_type[0] | m->sub_mb_type[1] |
|
|
nengel@2
|
894 m->sub_mb_type[2] | m->sub_mb_type[3]) ) {
|
|
nengel@2
|
895 ff_h264_pred_direct_motion_rec(mrc, mrs, s, m, &mb_type);
|
|
nengel@2
|
896 mrs->ref_cache[0][scan8[4]] =
|
|
nengel@2
|
897 mrs->ref_cache[1][scan8[4]] =
|
|
nengel@2
|
898 mrs->ref_cache[0][scan8[12]] =
|
|
nengel@2
|
899 mrs->ref_cache[1][scan8[12]] = PART_NOT_AVAILABLE;
|
|
nengel@2
|
900 }
|
|
nengel@2
|
901 }
|
|
nengel@2
|
902
|
|
nengel@2
|
903 for(list=0; list<s->list_count; list++){
|
|
nengel@2
|
904 for(i=0; i<4; i++){
|
|
nengel@2
|
905 if(IS_DIRECT(m->sub_mb_type[i])){
|
|
nengel@2
|
906 mrs->ref_cache[list][ scan8[4*i] ]=mrs->ref_cache[list][ scan8[4*i]+1 ];
|
|
nengel@2
|
907 continue;
|
|
nengel@2
|
908 } else {
|
|
nengel@2
|
909 mrs->ref_cache[list][ scan8[4*i] ]=mrs->ref_cache[list][ scan8[4*i]+1 ]=
|
|
nengel@2
|
910 mrs->ref_cache[list][ scan8[4*i]+8 ]=mrs->ref_cache[list][ scan8[4*i]+9 ]= m->ref_index[list][i];
|
|
nengel@2
|
911
|
|
nengel@2
|
912 if(IS_DIR(m->sub_mb_type[i], 0, list) ){
|
|
nengel@2
|
913 const int sub_mb_type= m->sub_mb_type[i];
|
|
nengel@2
|
914 const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1;
|
|
nengel@2
|
915
|
|
nengel@2
|
916 int sub_partition_count = IS_SUB_8X8(sub_mb_type) ? 1 : (IS_SUB_4X4(sub_mb_type)? 4 :2);
|
|
nengel@2
|
917 for(j=0; j<sub_partition_count; j++){
|
|
nengel@2
|
918 int mx, my;
|
|
nengel@2
|
919 const int index= 4*i + block_width*j;
|
|
nengel@2
|
920 int16_t (* mv_cache)[2]= &mrs->mv_cache[list][ scan8[index]];
|
|
nengel@2
|
921 pred_motion(mrc, mrs, s, index, block_width, list, mrs->ref_cache[list][ scan8[index] ], &mx, &my);
|
|
nengel@2
|
922
|
|
nengel@2
|
923 ADD_MVD(list)
|
|
nengel@2
|
924
|
|
nengel@2
|
925 if(IS_SUB_8X8(sub_mb_type)){
|
|
nengel@2
|
926 mv_cache[ 1 ][0]=
|
|
nengel@2
|
927 mv_cache[ 8 ][0]= mv_cache[ 9 ][0]= mx;
|
|
nengel@2
|
928 mv_cache[ 1 ][1]=
|
|
nengel@2
|
929 mv_cache[ 8 ][1]= mv_cache[ 9 ][1]= my;
|
|
nengel@2
|
930 }else if(IS_SUB_8X4(sub_mb_type)){
|
|
nengel@2
|
931 mv_cache[ 1 ][0]= mx;
|
|
nengel@2
|
932 mv_cache[ 1 ][1]= my;
|
|
nengel@2
|
933 }else if(IS_SUB_4X8(sub_mb_type)){
|
|
nengel@2
|
934 mv_cache[ 8 ][0]= mx;
|
|
nengel@2
|
935 mv_cache[ 8 ][1]= my;
|
|
nengel@2
|
936 }
|
|
nengel@2
|
937 mv_cache[ 0 ][0]= mx;
|
|
nengel@2
|
938 mv_cache[ 0 ][1]= my;
|
|
nengel@2
|
939 }
|
|
nengel@2
|
940 }else{
|
|
nengel@2
|
941 fill_rectangle(mrs->mv_cache [list][ scan8[4*i] ], 2, 2, 8, 0, 4);
|
|
nengel@2
|
942 }
|
|
nengel@2
|
943 }
|
|
nengel@2
|
944 }
|
|
nengel@2
|
945 }
|
|
nengel@2
|
946 } else if( IS_DIRECT(mb_type) ) {
|
|
nengel@2
|
947 mb_type &= ~MB_TYPE_16x16; //FIXME not nice
|
|
nengel@2
|
948 ff_h264_pred_direct_motion_rec(mrc, mrs, s, m, &mb_type);
|
|
nengel@2
|
949 }
|
|
nengel@2
|
950 else {
|
|
nengel@2
|
951 int list, i;
|
|
nengel@2
|
952 if(IS_16X16(mb_type)){
|
|
nengel@2
|
953 for(list=0; list<s->list_count; list++){
|
|
nengel@2
|
954 if(IS_DIR(mb_type, 0, list)){
|
|
nengel@2
|
955 int ref;
|
|
nengel@2
|
956 int mx,my;
|
|
nengel@2
|
957
|
|
nengel@2
|
958 ref = m->ref_index[list][0];
|
|
nengel@2
|
959 fill_rectangle(&mrs->ref_cache[list][ scan8[0] ], 4, 4, 8, ref, 1);
|
|
nengel@2
|
960 pred_motion(mrc, mrs, s, 0, 4, list, mrs->ref_cache[list][ scan8[0] ], &mx, &my);
|
|
nengel@2
|
961 ADD_MVD(list)
|
|
nengel@2
|
962 fill_rectangle(mrs->mv_cache[list][ scan8[0] ], 4, 4, 8, pack16to32(mx,my), 4);
|
|
nengel@2
|
963 }
|
|
nengel@2
|
964 }
|
|
nengel@2
|
965 }
|
|
nengel@2
|
966 else if(IS_16X8(mb_type)){
|
|
nengel@2
|
967 for(list=0; list<s->list_count; list++){
|
|
nengel@2
|
968 for(i=0; i<2; i++){
|
|
nengel@2
|
969 if(IS_DIR(mb_type, i, list)){
|
|
nengel@2
|
970 int ref;
|
|
nengel@2
|
971 int mx,my;
|
|
nengel@2
|
972 ref = m->ref_index[list][i];
|
|
nengel@2
|
973 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, ref, 1);
|
|
nengel@2
|
974
|
|
nengel@2
|
975 pred_16x8_motion(mrc, mrs, s, 8*i, list, mrs->ref_cache[list][scan8[0] + 16*i], &mx, &my);
|
|
nengel@2
|
976 ADD_MVD(list)
|
|
nengel@2
|
977
|
|
nengel@2
|
978 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4);
|
|
nengel@2
|
979 }else{
|
|
nengel@2
|
980 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1);
|
|
nengel@2
|
981 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
|
|
nengel@2
|
982 }
|
|
nengel@2
|
983 }
|
|
nengel@2
|
984 }
|
|
nengel@2
|
985
|
|
nengel@2
|
986 }else{
|
|
nengel@2
|
987 assert(IS_8X16(mb_type));
|
|
nengel@2
|
988
|
|
nengel@2
|
989 for(list=0; list<s->list_count; list++){
|
|
nengel@2
|
990 for(i=0; i<2; i++){
|
|
nengel@2
|
991 if(IS_DIR(mb_type, i, list)){ //FIXME optimize
|
|
nengel@2
|
992 int ref;
|
|
nengel@2
|
993 int mx,my;
|
|
nengel@2
|
994 ref = m->ref_index[list][i];
|
|
nengel@2
|
995 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, ref, 1);
|
|
nengel@2
|
996 pred_8x16_motion(mrc, mrs, s, i*4, list, mrs->ref_cache[list][ scan8[0] + 2*i ], &mx, &my);
|
|
nengel@2
|
997 ADD_MVD(list)
|
|
nengel@2
|
998 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4);
|
|
nengel@2
|
999 }else{
|
|
nengel@2
|
1000 fill_rectangle(&mrs->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1);
|
|
nengel@2
|
1001 fill_rectangle(mrs->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);
|
|
nengel@2
|
1002 }
|
|
nengel@2
|
1003 }
|
|
nengel@2
|
1004 }
|
|
nengel@2
|
1005 }
|
|
nengel@2
|
1006 }
|
|
nengel@2
|
1007
|
|
nengel@2
|
1008 if (IS_INTER(mb_type)||(IS_DIRECT(mb_type)))
|
|
nengel@2
|
1009 write_back_motion_rec(mrc, mrs, s, m, mb_type);
|
|
nengel@2
|
1010 m->mb_type = mrs->mb_type[mb_x]= mb_type;
|
|
nengel@2
|
1011
|
|
nengel@2
|
1012 return 0;
|
|
nengel@2
|
1013 }
|