blob: bc5c0d599ff031bb62a70c0f663059a3d9178d1c
1 | /* |
2 | * H.263/MPEG-4 backend for encoder and decoder |
3 | * Copyright (c) 2000,2001 Fabrice Bellard |
4 | * H.263+ support. |
5 | * Copyright (c) 2001 Juan J. Sierralta P |
6 | * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> |
7 | * |
8 | * This file is part of FFmpeg. |
9 | * |
10 | * FFmpeg is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU Lesser General Public |
12 | * License as published by the Free Software Foundation; either |
13 | * version 2.1 of the License, or (at your option) any later version. |
14 | * |
15 | * FFmpeg is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 | * Lesser General Public License for more details. |
19 | * |
20 | * You should have received a copy of the GNU Lesser General Public |
21 | * License along with FFmpeg; if not, write to the Free Software |
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 | */ |
24 | |
25 | /** |
26 | * @file |
27 | * H.263/MPEG-4 codec. |
28 | */ |
29 | |
30 | #include <limits.h> |
31 | |
32 | #include "avcodec.h" |
33 | #include "mpegvideo.h" |
34 | #include "h263.h" |
35 | #include "h263data.h" |
36 | #include "mathops.h" |
37 | #include "mpegutils.h" |
38 | #include "flv.h" |
39 | #include "mpeg4video.h" |
40 | |
41 | |
42 | void ff_h263_update_motion_val(MpegEncContext * s){ |
43 | const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; |
44 | //FIXME a lot of that is only needed for !low_delay |
45 | const int wrap = s->b8_stride; |
46 | const int xy = s->block_index[0]; |
47 | |
48 | s->current_picture.mbskip_table[mb_xy] = s->mb_skipped; |
49 | |
50 | if(s->mv_type != MV_TYPE_8X8){ |
51 | int motion_x, motion_y; |
52 | if (s->mb_intra) { |
53 | motion_x = 0; |
54 | motion_y = 0; |
55 | } else if (s->mv_type == MV_TYPE_16X16) { |
56 | motion_x = s->mv[0][0][0]; |
57 | motion_y = s->mv[0][0][1]; |
58 | } else /*if (s->mv_type == MV_TYPE_FIELD)*/ { |
59 | int i; |
60 | motion_x = s->mv[0][0][0] + s->mv[0][1][0]; |
61 | motion_y = s->mv[0][0][1] + s->mv[0][1][1]; |
62 | motion_x = (motion_x>>1) | (motion_x&1); |
63 | for(i=0; i<2; i++){ |
64 | s->p_field_mv_table[i][0][mb_xy][0]= s->mv[0][i][0]; |
65 | s->p_field_mv_table[i][0][mb_xy][1]= s->mv[0][i][1]; |
66 | } |
67 | s->current_picture.ref_index[0][4*mb_xy ] = |
68 | s->current_picture.ref_index[0][4*mb_xy + 1] = s->field_select[0][0]; |
69 | s->current_picture.ref_index[0][4*mb_xy + 2] = |
70 | s->current_picture.ref_index[0][4*mb_xy + 3] = s->field_select[0][1]; |
71 | } |
72 | |
73 | /* no update if 8X8 because it has been done during parsing */ |
74 | s->current_picture.motion_val[0][xy][0] = motion_x; |
75 | s->current_picture.motion_val[0][xy][1] = motion_y; |
76 | s->current_picture.motion_val[0][xy + 1][0] = motion_x; |
77 | s->current_picture.motion_val[0][xy + 1][1] = motion_y; |
78 | s->current_picture.motion_val[0][xy + wrap][0] = motion_x; |
79 | s->current_picture.motion_val[0][xy + wrap][1] = motion_y; |
80 | s->current_picture.motion_val[0][xy + 1 + wrap][0] = motion_x; |
81 | s->current_picture.motion_val[0][xy + 1 + wrap][1] = motion_y; |
82 | } |
83 | |
84 | if(s->encoding){ //FIXME encoding MUST be cleaned up |
85 | if (s->mv_type == MV_TYPE_8X8) |
86 | s->current_picture.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_8x8; |
87 | else if(s->mb_intra) |
88 | s->current_picture.mb_type[mb_xy] = MB_TYPE_INTRA; |
89 | else |
90 | s->current_picture.mb_type[mb_xy] = MB_TYPE_L0 | MB_TYPE_16x16; |
91 | } |
92 | } |
93 | |
94 | int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) |
95 | { |
96 | int x, y, wrap, a, c, pred_dc; |
97 | int16_t *dc_val; |
98 | |
99 | /* find prediction */ |
100 | if (n < 4) { |
101 | x = 2 * s->mb_x + (n & 1); |
102 | y = 2 * s->mb_y + ((n & 2) >> 1); |
103 | wrap = s->b8_stride; |
104 | dc_val = s->dc_val[0]; |
105 | } else { |
106 | x = s->mb_x; |
107 | y = s->mb_y; |
108 | wrap = s->mb_stride; |
109 | dc_val = s->dc_val[n - 4 + 1]; |
110 | } |
111 | /* B C |
112 | * A X |
113 | */ |
114 | a = dc_val[(x - 1) + (y) * wrap]; |
115 | c = dc_val[(x) + (y - 1) * wrap]; |
116 | |
117 | /* No prediction outside GOB boundary */ |
118 | if(s->first_slice_line && n!=3){ |
119 | if(n!=2) c= 1024; |
120 | if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; |
121 | } |
122 | /* just DC prediction */ |
123 | if (a != 1024 && c != 1024) |
124 | pred_dc = (a + c) >> 1; |
125 | else if (a != 1024) |
126 | pred_dc = a; |
127 | else |
128 | pred_dc = c; |
129 | |
130 | /* we assume pred is positive */ |
131 | *dc_val_ptr = &dc_val[x + y * wrap]; |
132 | return pred_dc; |
133 | } |
134 | |
135 | void ff_h263_loop_filter(MpegEncContext * s){ |
136 | int qp_c; |
137 | const int linesize = s->linesize; |
138 | const int uvlinesize= s->uvlinesize; |
139 | const int xy = s->mb_y * s->mb_stride + s->mb_x; |
140 | uint8_t *dest_y = s->dest[0]; |
141 | uint8_t *dest_cb= s->dest[1]; |
142 | uint8_t *dest_cr= s->dest[2]; |
143 | |
144 | /* |
145 | Diag Top |
146 | Left Center |
147 | */ |
148 | if (!IS_SKIP(s->current_picture.mb_type[xy])) { |
149 | qp_c= s->qscale; |
150 | s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize, linesize, qp_c); |
151 | s->h263dsp.h263_v_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c); |
152 | }else |
153 | qp_c= 0; |
154 | |
155 | if(s->mb_y){ |
156 | int qp_dt, qp_tt, qp_tc; |
157 | |
158 | if (IS_SKIP(s->current_picture.mb_type[xy - s->mb_stride])) |
159 | qp_tt=0; |
160 | else |
161 | qp_tt = s->current_picture.qscale_table[xy - s->mb_stride]; |
162 | |
163 | if(qp_c) |
164 | qp_tc= qp_c; |
165 | else |
166 | qp_tc= qp_tt; |
167 | |
168 | if(qp_tc){ |
169 | const int chroma_qp= s->chroma_qscale_table[qp_tc]; |
170 | s->h263dsp.h263_v_loop_filter(dest_y, linesize, qp_tc); |
171 | s->h263dsp.h263_v_loop_filter(dest_y + 8, linesize, qp_tc); |
172 | |
173 | s->h263dsp.h263_v_loop_filter(dest_cb, uvlinesize, chroma_qp); |
174 | s->h263dsp.h263_v_loop_filter(dest_cr, uvlinesize, chroma_qp); |
175 | } |
176 | |
177 | if(qp_tt) |
178 | s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize + 8, linesize, qp_tt); |
179 | |
180 | if(s->mb_x){ |
181 | if (qp_tt || IS_SKIP(s->current_picture.mb_type[xy - 1 - s->mb_stride])) |
182 | qp_dt= qp_tt; |
183 | else |
184 | qp_dt = s->current_picture.qscale_table[xy - 1 - s->mb_stride]; |
185 | |
186 | if(qp_dt){ |
187 | const int chroma_qp= s->chroma_qscale_table[qp_dt]; |
188 | s->h263dsp.h263_h_loop_filter(dest_y - 8 * linesize, linesize, qp_dt); |
189 | s->h263dsp.h263_h_loop_filter(dest_cb - 8 * uvlinesize, uvlinesize, chroma_qp); |
190 | s->h263dsp.h263_h_loop_filter(dest_cr - 8 * uvlinesize, uvlinesize, chroma_qp); |
191 | } |
192 | } |
193 | } |
194 | |
195 | if(qp_c){ |
196 | s->h263dsp.h263_h_loop_filter(dest_y + 8, linesize, qp_c); |
197 | if(s->mb_y + 1 == s->mb_height) |
198 | s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize + 8, linesize, qp_c); |
199 | } |
200 | |
201 | if(s->mb_x){ |
202 | int qp_lc; |
203 | if (qp_c || IS_SKIP(s->current_picture.mb_type[xy - 1])) |
204 | qp_lc= qp_c; |
205 | else |
206 | qp_lc = s->current_picture.qscale_table[xy - 1]; |
207 | |
208 | if(qp_lc){ |
209 | s->h263dsp.h263_h_loop_filter(dest_y, linesize, qp_lc); |
210 | if(s->mb_y + 1 == s->mb_height){ |
211 | const int chroma_qp= s->chroma_qscale_table[qp_lc]; |
212 | s->h263dsp.h263_h_loop_filter(dest_y + 8 * linesize, linesize, qp_lc); |
213 | s->h263dsp.h263_h_loop_filter(dest_cb, uvlinesize, chroma_qp); |
214 | s->h263dsp.h263_h_loop_filter(dest_cr, uvlinesize, chroma_qp); |
215 | } |
216 | } |
217 | } |
218 | } |
219 | |
220 | void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) |
221 | { |
222 | int x, y, wrap, a, c, pred_dc, scale, i; |
223 | int16_t *dc_val, *ac_val, *ac_val1; |
224 | |
225 | /* find prediction */ |
226 | if (n < 4) { |
227 | x = 2 * s->mb_x + (n & 1); |
228 | y = 2 * s->mb_y + (n>> 1); |
229 | wrap = s->b8_stride; |
230 | dc_val = s->dc_val[0]; |
231 | ac_val = s->ac_val[0][0]; |
232 | scale = s->y_dc_scale; |
233 | } else { |
234 | x = s->mb_x; |
235 | y = s->mb_y; |
236 | wrap = s->mb_stride; |
237 | dc_val = s->dc_val[n - 4 + 1]; |
238 | ac_val = s->ac_val[n - 4 + 1][0]; |
239 | scale = s->c_dc_scale; |
240 | } |
241 | |
242 | ac_val += ((y) * wrap + (x)) * 16; |
243 | ac_val1 = ac_val; |
244 | |
245 | /* B C |
246 | * A X |
247 | */ |
248 | a = dc_val[(x - 1) + (y) * wrap]; |
249 | c = dc_val[(x) + (y - 1) * wrap]; |
250 | |
251 | /* No prediction outside GOB boundary */ |
252 | if(s->first_slice_line && n!=3){ |
253 | if(n!=2) c= 1024; |
254 | if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; |
255 | } |
256 | |
257 | if (s->ac_pred) { |
258 | pred_dc = 1024; |
259 | if (s->h263_aic_dir) { |
260 | /* left prediction */ |
261 | if (a != 1024) { |
262 | ac_val -= 16; |
263 | for(i=1;i<8;i++) { |
264 | block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; |
265 | } |
266 | pred_dc = a; |
267 | } |
268 | } else { |
269 | /* top prediction */ |
270 | if (c != 1024) { |
271 | ac_val -= 16 * wrap; |
272 | for(i=1;i<8;i++) { |
273 | block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; |
274 | } |
275 | pred_dc = c; |
276 | } |
277 | } |
278 | } else { |
279 | /* just DC prediction */ |
280 | if (a != 1024 && c != 1024) |
281 | pred_dc = (a + c) >> 1; |
282 | else if (a != 1024) |
283 | pred_dc = a; |
284 | else |
285 | pred_dc = c; |
286 | } |
287 | |
288 | /* we assume pred is positive */ |
289 | block[0]=block[0]*scale + pred_dc; |
290 | |
291 | if (block[0] < 0) |
292 | block[0] = 0; |
293 | else |
294 | block[0] |= 1; |
295 | |
296 | /* Update AC/DC tables */ |
297 | dc_val[(x) + (y) * wrap] = block[0]; |
298 | |
299 | /* left copy */ |
300 | for(i=1;i<8;i++) |
301 | ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; |
302 | /* top copy */ |
303 | for(i=1;i<8;i++) |
304 | ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; |
305 | } |
306 | |
307 | int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, |
308 | int *px, int *py) |
309 | { |
310 | int wrap; |
311 | int16_t *A, *B, *C, (*mot_val)[2]; |
312 | static const int off[4]= {2, 1, 1, -1}; |
313 | |
314 | wrap = s->b8_stride; |
315 | mot_val = s->current_picture.motion_val[dir] + s->block_index[block]; |
316 | |
317 | A = mot_val[ - 1]; |
318 | /* special case for first (slice) line */ |
319 | if (s->first_slice_line && block<3) { |
320 | // we can't just change some MVs to simulate that as we need them for the B-frames (and ME) |
321 | // and if we ever support non rectangular objects than we need to do a few ifs here anyway :( |
322 | if(block==0){ //most common case |
323 | if(s->mb_x == s->resync_mb_x){ //rare |
324 | *px= *py = 0; |
325 | }else if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare |
326 | C = mot_val[off[block] - wrap]; |
327 | if(s->mb_x==0){ |
328 | *px = C[0]; |
329 | *py = C[1]; |
330 | }else{ |
331 | *px = mid_pred(A[0], 0, C[0]); |
332 | *py = mid_pred(A[1], 0, C[1]); |
333 | } |
334 | }else{ |
335 | *px = A[0]; |
336 | *py = A[1]; |
337 | } |
338 | }else if(block==1){ |
339 | if(s->mb_x + 1 == s->resync_mb_x && s->h263_pred){ //rare |
340 | C = mot_val[off[block] - wrap]; |
341 | *px = mid_pred(A[0], 0, C[0]); |
342 | *py = mid_pred(A[1], 0, C[1]); |
343 | }else{ |
344 | *px = A[0]; |
345 | *py = A[1]; |
346 | } |
347 | }else{ /* block==2*/ |
348 | B = mot_val[ - wrap]; |
349 | C = mot_val[off[block] - wrap]; |
350 | if(s->mb_x == s->resync_mb_x) //rare |
351 | A[0]=A[1]=0; |
352 | |
353 | *px = mid_pred(A[0], B[0], C[0]); |
354 | *py = mid_pred(A[1], B[1], C[1]); |
355 | } |
356 | } else { |
357 | B = mot_val[ - wrap]; |
358 | C = mot_val[off[block] - wrap]; |
359 | *px = mid_pred(A[0], B[0], C[0]); |
360 | *py = mid_pred(A[1], B[1], C[1]); |
361 | } |
362 | return *mot_val; |
363 | } |
364 |