Mercurial > libavcodec.hg
annotate wmv2dec.c @ 11032:01bd040f8607 libavcodec
Unroll main loop so the edge==0 case is seperate.
This allows many things to be simplified away.
h264 decoder is overall 1% faster with a mbaff sample and
0.1% slower with the cathedral sample, probably because the slow loop
filter code must be loaded into the code cache for each first MB of each
row but isnt used for the following MBs.
author | michael |
---|---|
date | Thu, 28 Jan 2010 01:24:25 +0000 |
parents | d0657e337f91 |
children | 8a4984c5cacc |
rev | line source |
---|---|
5939 | 1 /* |
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
8627
diff
changeset
|
2 * Copyright (c) 2002 The FFmpeg Project |
5939 | 3 * |
4 * This file is part of FFmpeg. | |
5 * | |
6 * FFmpeg is free software; you can redistribute it and/or | |
7 * modify it under the terms of the GNU Lesser General Public | |
8 * License as published by the Free Software Foundation; either | |
9 * version 2.1 of the License, or (at your option) any later version. | |
10 * | |
11 * FFmpeg is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
17 * License along with FFmpeg; if not, write to the Free Software | |
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 */ | |
20 | |
21 #include "avcodec.h" | |
22 #include "dsputil.h" | |
23 #include "mpegvideo.h" | |
10828 | 24 #include "h263.h" |
8627
d6bab465b82c
moves mid_pred() into mathops.h (with arch specific code split by directory)
aurel
parents:
7040
diff
changeset
|
25 #include "mathops.h" |
5939 | 26 #include "msmpeg4.h" |
27 #include "msmpeg4data.h" | |
28 #include "intrax8.h" | |
29 #include "wmv2.h" | |
30 | |
31 | |
32 static void parse_mb_skip(Wmv2Context * w){ | |
33 int mb_x, mb_y; | |
34 MpegEncContext * const s= &w->s; | |
35 uint32_t * const mb_type= s->current_picture_ptr->mb_type; | |
36 | |
37 w->skip_type= get_bits(&s->gb, 2); | |
38 switch(w->skip_type){ | |
39 case SKIP_TYPE_NONE: | |
40 for(mb_y=0; mb_y<s->mb_height; mb_y++){ | |
41 for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
42 mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_16x16 | MB_TYPE_L0; | |
43 } | |
44 } | |
45 break; | |
46 case SKIP_TYPE_MPEG: | |
47 for(mb_y=0; mb_y<s->mb_height; mb_y++){ | |
48 for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
49 mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; | |
50 } | |
51 } | |
52 break; | |
53 case SKIP_TYPE_ROW: | |
54 for(mb_y=0; mb_y<s->mb_height; mb_y++){ | |
55 if(get_bits1(&s->gb)){ | |
56 for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
57 mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; | |
58 } | |
59 }else{ | |
60 for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
61 mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; | |
62 } | |
63 } | |
64 } | |
65 break; | |
66 case SKIP_TYPE_COL: | |
67 for(mb_x=0; mb_x<s->mb_width; mb_x++){ | |
68 if(get_bits1(&s->gb)){ | |
69 for(mb_y=0; mb_y<s->mb_height; mb_y++){ | |
70 mb_type[mb_y*s->mb_stride + mb_x]= MB_TYPE_SKIP | MB_TYPE_16x16 | MB_TYPE_L0; | |
71 } | |
72 }else{ | |
73 for(mb_y=0; mb_y<s->mb_height; mb_y++){ | |
74 mb_type[mb_y*s->mb_stride + mb_x]= (get_bits1(&s->gb) ? MB_TYPE_SKIP : 0) | MB_TYPE_16x16 | MB_TYPE_L0; | |
75 } | |
76 } | |
77 } | |
78 break; | |
79 } | |
80 } | |
81 | |
82 static int decode_ext_header(Wmv2Context *w){ | |
83 MpegEncContext * const s= &w->s; | |
84 GetBitContext gb; | |
85 int fps; | |
86 int code; | |
87 | |
88 if(s->avctx->extradata_size<4) return -1; | |
89 | |
90 init_get_bits(&gb, s->avctx->extradata, s->avctx->extradata_size*8); | |
91 | |
92 fps = get_bits(&gb, 5); | |
93 s->bit_rate = get_bits(&gb, 11)*1024; | |
94 w->mspel_bit = get_bits1(&gb); | |
95 s->loop_filter = get_bits1(&gb); | |
96 w->abt_flag = get_bits1(&gb); | |
97 w->j_type_bit = get_bits1(&gb); | |
98 w->top_left_mv_flag= get_bits1(&gb); | |
99 w->per_mb_rl_bit = get_bits1(&gb); | |
100 code = get_bits(&gb, 3); | |
101 | |
102 if(code==0) return -1; | |
103 | |
104 s->slice_height = s->mb_height / code; | |
105 | |
106 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ | |
107 av_log(s->avctx, AV_LOG_DEBUG, "fps:%d, br:%d, qpbit:%d, abt_flag:%d, j_type_bit:%d, tl_mv_flag:%d, mbrl_bit:%d, code:%d, loop_filter:%d, slices:%d\n", | |
108 fps, s->bit_rate, w->mspel_bit, w->abt_flag, w->j_type_bit, w->top_left_mv_flag, w->per_mb_rl_bit, code, s->loop_filter, | |
109 code); | |
110 } | |
111 return 0; | |
112 } | |
113 | |
114 int ff_wmv2_decode_picture_header(MpegEncContext * s) | |
115 { | |
116 Wmv2Context * const w= (Wmv2Context*)s; | |
117 int code; | |
118 | |
119 #if 0 | |
120 { | |
121 int i; | |
122 for(i=0; i<s->gb.size*8; i++) | |
123 printf("%d", get_bits1(&s->gb)); | |
124 // get_bits1(&s->gb); | |
125 printf("END\n"); | |
126 return -1; | |
127 } | |
128 #endif | |
129 if(s->picture_number==0) | |
130 decode_ext_header(w); | |
131 | |
132 s->pict_type = get_bits1(&s->gb) + 1; | |
6481 | 133 if(s->pict_type == FF_I_TYPE){ |
5939 | 134 code = get_bits(&s->gb, 7); |
135 av_log(s->avctx, AV_LOG_DEBUG, "I7:%X/\n", code); | |
136 } | |
137 s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); | |
6149 | 138 if(s->qscale <= 0) |
5939 | 139 return -1; |
140 | |
141 return 0; | |
142 } | |
143 | |
144 int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s) | |
145 { | |
146 Wmv2Context * const w= (Wmv2Context*)s; | |
147 | |
6481 | 148 if (s->pict_type == FF_I_TYPE) { |
5939 | 149 if(w->j_type_bit) w->j_type= get_bits1(&s->gb); |
150 else w->j_type= 0; //FIXME check | |
151 | |
152 if(!w->j_type){ | |
153 if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); | |
154 else s->per_mb_rl_table= 0; | |
155 | |
156 if(!s->per_mb_rl_table){ | |
157 s->rl_chroma_table_index = decode012(&s->gb); | |
158 s->rl_table_index = decode012(&s->gb); | |
159 } | |
160 | |
161 s->dc_table_index = get_bits1(&s->gb); | |
162 } | |
163 s->inter_intra_pred= 0; | |
164 s->no_rounding = 1; | |
165 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ | |
166 av_log(s->avctx, AV_LOG_DEBUG, "qscale:%d rlc:%d rl:%d dc:%d mbrl:%d j_type:%d \n", | |
167 s->qscale, | |
168 s->rl_chroma_table_index, | |
169 s->rl_table_index, | |
170 s->dc_table_index, | |
171 s->per_mb_rl_table, | |
172 w->j_type); | |
173 } | |
174 }else{ | |
175 int cbp_index; | |
176 w->j_type=0; | |
177 | |
178 parse_mb_skip(w); | |
179 cbp_index= decode012(&s->gb); | |
180 if(s->qscale <= 10){ | |
181 int map[3]= {0,2,1}; | |
182 w->cbp_table_index= map[cbp_index]; | |
183 }else if(s->qscale <= 20){ | |
184 int map[3]= {1,0,2}; | |
185 w->cbp_table_index= map[cbp_index]; | |
186 }else{ | |
187 int map[3]= {2,1,0}; | |
188 w->cbp_table_index= map[cbp_index]; | |
189 } | |
190 | |
191 if(w->mspel_bit) s->mspel= get_bits1(&s->gb); | |
192 else s->mspel= 0; //FIXME check | |
193 | |
194 if(w->abt_flag){ | |
195 w->per_mb_abt= get_bits1(&s->gb)^1; | |
196 if(!w->per_mb_abt){ | |
197 w->abt_type= decode012(&s->gb); | |
198 } | |
199 } | |
200 | |
201 if(w->per_mb_rl_bit) s->per_mb_rl_table= get_bits1(&s->gb); | |
202 else s->per_mb_rl_table= 0; | |
203 | |
204 if(!s->per_mb_rl_table){ | |
205 s->rl_table_index = decode012(&s->gb); | |
206 s->rl_chroma_table_index = s->rl_table_index; | |
207 } | |
208 | |
209 s->dc_table_index = get_bits1(&s->gb); | |
210 s->mv_table_index = get_bits1(&s->gb); | |
211 | |
212 s->inter_intra_pred= 0;//(s->width*s->height < 320*240 && s->bit_rate<=II_BITRATE); | |
213 s->no_rounding ^= 1; | |
214 | |
215 if(s->avctx->debug&FF_DEBUG_PICT_INFO){ | |
216 av_log(s->avctx, AV_LOG_DEBUG, "rl:%d rlc:%d dc:%d mv:%d mbrl:%d qp:%d mspel:%d per_mb_abt:%d abt_type:%d cbp:%d ii:%d\n", | |
217 s->rl_table_index, | |
218 s->rl_chroma_table_index, | |
219 s->dc_table_index, | |
220 s->mv_table_index, | |
221 s->per_mb_rl_table, | |
222 s->qscale, | |
223 s->mspel, | |
224 w->per_mb_abt, | |
225 w->abt_type, | |
226 w->cbp_table_index, | |
227 s->inter_intra_pred); | |
228 } | |
229 } | |
230 s->esc3_level_length= 0; | |
231 s->esc3_run_length= 0; | |
232 | |
233 s->picture_number++; //FIXME ? | |
234 | |
235 | |
236 if(w->j_type){ | |
237 ff_intrax8_decode_picture(&w->x8, 2*s->qscale, (s->qscale-1)|1 ); | |
238 return 1; | |
239 } | |
240 | |
241 return 0; | |
242 } | |
243 | |
244 static inline int wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr){ | |
245 MpegEncContext * const s= &w->s; | |
246 int ret; | |
247 | |
248 ret= ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); | |
249 | |
250 if(ret<0) return -1; | |
251 | |
252 if((((*mx_ptr)|(*my_ptr)) & 1) && s->mspel) | |
253 w->hshift= get_bits1(&s->gb); | |
254 else | |
255 w->hshift= 0; | |
256 | |
257 //printf("%d %d ", *mx_ptr, *my_ptr); | |
258 | |
259 return 0; | |
260 } | |
261 | |
262 static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py){ | |
263 MpegEncContext * const s= &w->s; | |
264 int xy, wrap, diff, type; | |
265 int16_t *A, *B, *C, *mot_val; | |
266 | |
267 wrap = s->b8_stride; | |
268 xy = s->block_index[0]; | |
269 | |
270 mot_val = s->current_picture.motion_val[0][xy]; | |
271 | |
272 A = s->current_picture.motion_val[0][xy - 1]; | |
273 B = s->current_picture.motion_val[0][xy - wrap]; | |
274 C = s->current_picture.motion_val[0][xy + 2 - wrap]; | |
275 | |
276 if(s->mb_x && !s->first_slice_line && !s->mspel && w->top_left_mv_flag) | |
277 diff= FFMAX(FFABS(A[0] - B[0]), FFABS(A[1] - B[1])); | |
278 else | |
279 diff=0; | |
280 | |
281 if(diff >= 8) | |
282 type= get_bits1(&s->gb); | |
283 else | |
284 type= 2; | |
285 | |
286 if(type == 0){ | |
287 *px= A[0]; | |
288 *py= A[1]; | |
289 }else if(type == 1){ | |
290 *px= B[0]; | |
291 *py= B[1]; | |
292 }else{ | |
293 /* special case for first (slice) line */ | |
294 if (s->first_slice_line) { | |
295 *px = A[0]; | |
296 *py = A[1]; | |
297 } else { | |
298 *px = mid_pred(A[0], B[0], C[0]); | |
299 *py = mid_pred(A[1], B[1], C[1]); | |
300 } | |
301 } | |
302 | |
303 return mot_val; | |
304 } | |
305 | |
306 static inline int wmv2_decode_inter_block(Wmv2Context *w, DCTELEM *block, int n, int cbp){ | |
307 MpegEncContext * const s= &w->s; | |
308 static const int sub_cbp_table[3]= {2,3,1}; | |
309 int sub_cbp; | |
310 | |
311 if(!cbp){ | |
312 s->block_last_index[n] = -1; | |
313 | |
314 return 0; | |
315 } | |
316 | |
317 if(w->per_block_abt) | |
318 w->abt_type= decode012(&s->gb); | |
319 #if 0 | |
320 if(w->per_block_abt) | |
321 printf("B%d", w->abt_type); | |
322 #endif | |
323 w->abt_type_table[n]= w->abt_type; | |
324 | |
325 if(w->abt_type){ | |
326 // const uint8_t *scantable= w->abt_scantable[w->abt_type-1].permutated; | |
327 const uint8_t *scantable= w->abt_scantable[w->abt_type-1].scantable; | |
328 // const uint8_t *scantable= w->abt_type-1 ? w->abt_scantable[1].permutated : w->abt_scantable[0].scantable; | |
329 | |
330 sub_cbp= sub_cbp_table[ decode012(&s->gb) ]; | |
331 // printf("S%d", sub_cbp); | |
332 | |
333 if(sub_cbp&1){ | |
334 if (ff_msmpeg4_decode_block(s, block, n, 1, scantable) < 0) | |
335 return -1; | |
336 } | |
337 | |
338 if(sub_cbp&2){ | |
339 if (ff_msmpeg4_decode_block(s, w->abt_block2[n], n, 1, scantable) < 0) | |
340 return -1; | |
341 } | |
342 s->block_last_index[n] = 63; | |
343 | |
344 return 0; | |
345 }else{ | |
346 return ff_msmpeg4_decode_block(s, block, n, 1, s->inter_scantable.permutated); | |
347 } | |
348 } | |
349 | |
350 | |
351 int ff_wmv2_decode_mb(MpegEncContext *s, DCTELEM block[6][64]) | |
352 { | |
353 Wmv2Context * const w= (Wmv2Context*)s; | |
354 int cbp, code, i; | |
355 uint8_t *coded_val; | |
356 | |
357 if(w->j_type) return 0; | |
358 | |
6481 | 359 if (s->pict_type == FF_P_TYPE) { |
5939 | 360 if(IS_SKIP(s->current_picture.mb_type[s->mb_y * s->mb_stride + s->mb_x])){ |
361 /* skip mb */ | |
362 s->mb_intra = 0; | |
363 for(i=0;i<6;i++) | |
364 s->block_last_index[i] = -1; | |
365 s->mv_dir = MV_DIR_FORWARD; | |
366 s->mv_type = MV_TYPE_16X16; | |
367 s->mv[0][0][0] = 0; | |
368 s->mv[0][0][1] = 0; | |
369 s->mb_skipped = 1; | |
370 w->hshift=0; | |
371 return 0; | |
372 } | |
373 | |
374 code = get_vlc2(&s->gb, ff_mb_non_intra_vlc[w->cbp_table_index].table, MB_NON_INTRA_VLC_BITS, 3); | |
375 if (code < 0) | |
376 return -1; | |
377 s->mb_intra = (~code & 0x40) >> 6; | |
378 | |
379 cbp = code & 0x3f; | |
380 } else { | |
381 s->mb_intra = 1; | |
382 code = get_vlc2(&s->gb, ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS, 2); | |
383 if (code < 0){ | |
384 av_log(s->avctx, AV_LOG_ERROR, "II-cbp illegal at %d %d\n", s->mb_x, s->mb_y); | |
385 return -1; | |
386 } | |
387 /* predict coded block pattern */ | |
388 cbp = 0; | |
389 for(i=0;i<6;i++) { | |
390 int val = ((code >> (5 - i)) & 1); | |
391 if (i < 4) { | |
392 int pred = ff_msmpeg4_coded_block_pred(s, i, &coded_val); | |
393 val = val ^ pred; | |
394 *coded_val = val; | |
395 } | |
396 cbp |= val << (5 - i); | |
397 } | |
398 } | |
399 | |
400 if (!s->mb_intra) { | |
401 int mx, my; | |
402 //printf("P at %d %d\n", s->mb_x, s->mb_y); | |
403 wmv2_pred_motion(w, &mx, &my); | |
404 | |
405 if(cbp){ | |
406 s->dsp.clear_blocks(s->block[0]); | |
407 if(s->per_mb_rl_table){ | |
408 s->rl_table_index = decode012(&s->gb); | |
409 s->rl_chroma_table_index = s->rl_table_index; | |
410 } | |
411 | |
412 if(w->abt_flag && w->per_mb_abt){ | |
413 w->per_block_abt= get_bits1(&s->gb); | |
414 if(!w->per_block_abt) | |
415 w->abt_type= decode012(&s->gb); | |
416 }else | |
417 w->per_block_abt=0; | |
418 } | |
419 | |
420 if (wmv2_decode_motion(w, &mx, &my) < 0) | |
421 return -1; | |
422 | |
423 s->mv_dir = MV_DIR_FORWARD; | |
424 s->mv_type = MV_TYPE_16X16; | |
425 s->mv[0][0][0] = mx; | |
426 s->mv[0][0][1] = my; | |
427 | |
428 for (i = 0; i < 6; i++) { | |
429 if (wmv2_decode_inter_block(w, block[i], i, (cbp >> (5 - i)) & 1) < 0) | |
430 { | |
431 av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding inter block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); | |
432 return -1; | |
433 } | |
434 } | |
435 } else { | |
6481 | 436 //if(s->pict_type==FF_P_TYPE) |
5939 | 437 // printf("%d%d ", s->inter_intra_pred, cbp); |
438 //printf("I at %d %d %d %06X\n", s->mb_x, s->mb_y, ((cbp&3)? 1 : 0) +((cbp&0x3C)? 2 : 0), show_bits(&s->gb, 24)); | |
439 s->ac_pred = get_bits1(&s->gb); | |
440 if(s->inter_intra_pred){ | |
441 s->h263_aic_dir= get_vlc2(&s->gb, ff_inter_intra_vlc.table, INTER_INTRA_VLC_BITS, 1); | |
442 // printf("%d%d %d %d/", s->ac_pred, s->h263_aic_dir, s->mb_x, s->mb_y); | |
443 } | |
444 if(s->per_mb_rl_table && cbp){ | |
445 s->rl_table_index = decode012(&s->gb); | |
446 s->rl_chroma_table_index = s->rl_table_index; | |
447 } | |
448 | |
449 s->dsp.clear_blocks(s->block[0]); | |
450 for (i = 0; i < 6; i++) { | |
451 if (ff_msmpeg4_decode_block(s, block[i], i, (cbp >> (5 - i)) & 1, NULL) < 0) | |
452 { | |
453 av_log(s->avctx, AV_LOG_ERROR, "\nerror while decoding intra block: %d x %d (%d)\n", s->mb_x, s->mb_y, i); | |
454 return -1; | |
455 } | |
456 } | |
457 } | |
458 | |
459 return 0; | |
460 } | |
461 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6481
diff
changeset
|
462 static av_cold int wmv2_decode_init(AVCodecContext *avctx){ |
5939 | 463 Wmv2Context * const w= avctx->priv_data; |
464 | |
465 if(avctx->idct_algo==FF_IDCT_AUTO){ | |
466 avctx->idct_algo=FF_IDCT_WMV2; | |
467 } | |
468 | |
10822
9ccc13d1144d
Move AVCodecs from h263dec.c to msmpeg4.c and disentangle init decode init.
michael
parents:
9028
diff
changeset
|
469 if(ff_msmpeg4_decode_init(avctx) < 0) |
5939 | 470 return -1; |
471 | |
472 ff_wmv2_common_init(w); | |
473 | |
474 ff_intrax8_common_init(&w->x8,&w->s); | |
475 | |
476 return 0; | |
477 } | |
478 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
6481
diff
changeset
|
479 static av_cold int wmv2_decode_end(AVCodecContext *avctx) |
6176
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
480 { |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
481 Wmv2Context *w = avctx->priv_data; |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
482 |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
483 ff_intrax8_common_end(&w->x8); |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
484 return ff_h263_decode_end(avctx); |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
485 } |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
486 |
5939 | 487 AVCodec wmv2_decoder = { |
488 "wmv2", | |
489 CODEC_TYPE_VIDEO, | |
490 CODEC_ID_WMV2, | |
491 sizeof(Wmv2Context), | |
492 wmv2_decode_init, | |
493 NULL, | |
6176
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
6149
diff
changeset
|
494 wmv2_decode_end, |
5939 | 495 ff_h263_decode_frame, |
496 CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6710
diff
changeset
|
497 .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), |
9028 | 498 .pix_fmts= ff_pixfmt_list_420, |
5939 | 499 }; |