/src/libldac/src/pack_ldac.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2003 - 2016 Sony Corporation |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include "ldac.h" |
18 | | |
19 | | /*************************************************************************************************** |
20 | | Pack and Store from MSB |
21 | | ***************************************************************************************************/ |
22 | | static void pack_store_ldac( |
23 | | int idata, |
24 | | int nbits, |
25 | | STREAM *p_block, |
26 | | int *p_loc) |
27 | 6.64k | { |
28 | 6.64k | STREAM *p_bufptr; |
29 | 6.64k | register int bpos; |
30 | 6.64k | register unsigned int tmp; |
31 | | |
32 | 6.64k | p_bufptr = p_block + (*p_loc >> LDAC_LOC_SHIFT); |
33 | 6.64k | bpos = *p_loc & LDAC_LOC_MASK; |
34 | | |
35 | 6.64k | tmp = (idata << (24-nbits)) & 0xffffff; |
36 | 6.64k | tmp >>= bpos; |
37 | 6.64k | *p_bufptr++ |= (tmp>>16); |
38 | 6.64k | *p_bufptr++ = (tmp>>8) & 0xff; |
39 | 6.64k | *p_bufptr = tmp & 0xff; |
40 | | |
41 | 6.64k | *p_loc += nbits; |
42 | | |
43 | 6.64k | return; |
44 | 6.64k | } |
45 | | |
46 | | |
47 | | /*************************************************************************************************** |
48 | | Pack Frame Header |
49 | | ***************************************************************************************************/ |
50 | | DECLFUNC void pack_frame_header_ldac( |
51 | | int smplrate_id, |
52 | | int chconfig_id, |
53 | | int frame_length, |
54 | | int frame_status, |
55 | | STREAM *p_stream) |
56 | 22 | { |
57 | 22 | int loc = 0; |
58 | | |
59 | 22 | pack_store_ldac(LDAC_SYNCWORD, LDAC_SYNCWORDBITS, p_stream, &loc); |
60 | | |
61 | 22 | pack_store_ldac(smplrate_id, LDAC_SMPLRATEBITS, p_stream, &loc); |
62 | | |
63 | 22 | pack_store_ldac(chconfig_id, LDAC_CHCONFIG2BITS, p_stream, &loc); |
64 | | |
65 | 22 | pack_store_ldac(frame_length-1, LDAC_FRAMELEN2BITS, p_stream, &loc); |
66 | | |
67 | 22 | pack_store_ldac(frame_status, LDAC_FRAMESTATBITS, p_stream, &loc); |
68 | | |
69 | 22 | return; |
70 | 22 | } |
71 | | |
72 | | /*************************************************************************************************** |
73 | | Pack Frame Alignment |
74 | | ***************************************************************************************************/ |
75 | | static void pack_frame_alignment_ldac( |
76 | | STREAM *p_stream, |
77 | | int *p_loc, |
78 | | int nbytes_frame) |
79 | 22 | { |
80 | 22 | int i; |
81 | 22 | int nbytes_filled; |
82 | | |
83 | 22 | nbytes_filled = nbytes_frame - *p_loc / LDAC_BYTESIZE; |
84 | | |
85 | 44 | for (i = 0; i < nbytes_filled; i++) { |
86 | 22 | pack_store_ldac(LDAC_FILLCODE, LDAC_BYTESIZE, p_stream, p_loc); |
87 | 22 | } |
88 | | |
89 | 22 | return; |
90 | 22 | } |
91 | | |
92 | | /*************************************************************************************************** |
93 | | Pack Byte Alignment |
94 | | ***************************************************************************************************/ |
95 | 44 | #define pack_block_alignment_ldac(p_stream, p_loc) pack_byte_alignment_ldac((p_stream), (p_loc)) |
96 | | |
97 | | static void pack_byte_alignment_ldac( |
98 | | STREAM *p_stream, |
99 | | int *p_loc) |
100 | 44 | { |
101 | 44 | int nbits_padding; |
102 | | |
103 | 44 | nbits_padding = ((*p_loc + LDAC_BYTESIZE - 1) / LDAC_BYTESIZE) * LDAC_BYTESIZE - *p_loc; |
104 | | |
105 | 44 | if (nbits_padding > 0) { |
106 | 0 | pack_store_ldac(0, nbits_padding, p_stream, p_loc); |
107 | 0 | } |
108 | | |
109 | 44 | return; |
110 | 44 | } |
111 | | |
112 | | /*************************************************************************************************** |
113 | | Pack Band Info |
114 | | ***************************************************************************************************/ |
115 | | static void pack_band_info_ldac( |
116 | | AB *p_ab, |
117 | | STREAM *p_stream, |
118 | | int *p_loc) |
119 | 44 | { |
120 | 44 | pack_store_ldac(p_ab->nbands-LDAC_BAND_OFFSET, LDAC_NBANDBITS, p_stream, p_loc); |
121 | | |
122 | 44 | pack_store_ldac(LDAC_FALSE, LDAC_FLAGBITS, p_stream, p_loc); |
123 | | |
124 | 44 | return; |
125 | 44 | } |
126 | | |
127 | | /*************************************************************************************************** |
128 | | Pack Gradient Data |
129 | | ***************************************************************************************************/ |
130 | | static void pack_gradient_ldac( |
131 | | AB *p_ab, |
132 | | STREAM *p_stream, |
133 | | int *p_loc) |
134 | 44 | { |
135 | 44 | pack_store_ldac(p_ab->grad_mode, LDAC_GRADMODEBITS, p_stream, p_loc); |
136 | | |
137 | 44 | if (p_ab->grad_mode == LDAC_MODE_0) { |
138 | 44 | pack_store_ldac(p_ab->grad_qu_l, LDAC_GRADQU0BITS, p_stream, p_loc); |
139 | | |
140 | 44 | pack_store_ldac(p_ab->grad_qu_h-1, LDAC_GRADQU0BITS, p_stream, p_loc); |
141 | | |
142 | 44 | pack_store_ldac(p_ab->grad_os_l, LDAC_GRADOSBITS, p_stream, p_loc); |
143 | | |
144 | 44 | pack_store_ldac(p_ab->grad_os_h, LDAC_GRADOSBITS, p_stream, p_loc); |
145 | 44 | } |
146 | 0 | else { |
147 | 0 | pack_store_ldac(p_ab->grad_qu_l, LDAC_GRADQU1BITS, p_stream, p_loc); |
148 | |
|
149 | 0 | pack_store_ldac(p_ab->grad_os_l, LDAC_GRADOSBITS, p_stream, p_loc); |
150 | 0 | } |
151 | | |
152 | 44 | pack_store_ldac(p_ab->nadjqus, LDAC_NADJQUBITS, p_stream, p_loc); |
153 | | |
154 | 44 | return; |
155 | 44 | } |
156 | | |
157 | | /*************************************************************************************************** |
158 | | Subfunction: Pack Scale Factor Data - Mode 0 |
159 | | ***************************************************************************************************/ |
160 | | static void pack_scale_factor_0_ldac( |
161 | | AC *p_ac, |
162 | | STREAM *p_stream, |
163 | | int *p_loc) |
164 | 44 | { |
165 | 44 | HCENC *p_hcsf; |
166 | 44 | int iqu; |
167 | 44 | int nqus = p_ac->p_ab->nqus; |
168 | 44 | int dif, val0, val1; |
169 | 44 | const unsigned char *p_tbl; |
170 | | |
171 | 44 | pack_store_ldac(p_ac->sfc_bitlen-LDAC_MINSFCBLEN_0, LDAC_SFCBLENBITS, p_stream, p_loc); |
172 | | |
173 | 44 | pack_store_ldac(p_ac->sfc_offset, LDAC_IDSFBITS, p_stream, p_loc); |
174 | | |
175 | 44 | pack_store_ldac(p_ac->sfc_weight, LDAC_SFCWTBLBITS, p_stream, p_loc); |
176 | | |
177 | 44 | p_tbl = gaa_sfcwgt_ldac[p_ac->sfc_weight]; |
178 | 44 | val0 = p_ac->a_idsf[0] + p_tbl[0]; |
179 | | |
180 | 44 | pack_store_ldac(val0-p_ac->sfc_offset, p_ac->sfc_bitlen, p_stream, p_loc); |
181 | | |
182 | 44 | p_hcsf = ga_hcenc_sf0_ldac + (p_ac->sfc_bitlen-LDAC_MINSFCBLEN_0); |
183 | 1.14k | for (iqu = 1; iqu < nqus; iqu++) { |
184 | 1.10k | val1 = p_ac->a_idsf[iqu] + p_tbl[iqu]; |
185 | 1.10k | dif = (val1 - val0) & p_hcsf->mask; |
186 | 1.10k | pack_store_ldac(hc_word_ldac(p_hcsf->p_tbl+dif), hc_len_ldac(p_hcsf->p_tbl+dif), p_stream, p_loc); |
187 | 1.10k | val0 = val1; |
188 | 1.10k | } |
189 | | |
190 | 44 | return; |
191 | 44 | } |
192 | | |
193 | | /*************************************************************************************************** |
194 | | Subfunction: Pack Scale Factor Data - Mode 1 |
195 | | ***************************************************************************************************/ |
196 | | static void pack_scale_factor_1_ldac( |
197 | | AC *p_ac, |
198 | | STREAM *p_stream, |
199 | | int *p_loc) |
200 | 0 | { |
201 | 0 | int iqu; |
202 | 0 | int nqus = p_ac->p_ab->nqus; |
203 | 0 | const unsigned char *p_tbl; |
204 | |
|
205 | 0 | pack_store_ldac(p_ac->sfc_bitlen-LDAC_MINSFCBLEN_1, LDAC_SFCBLENBITS, p_stream, p_loc); |
206 | |
|
207 | 0 | if (p_ac->sfc_bitlen > 4) { |
208 | 0 | for (iqu = 0; iqu < nqus; iqu++) { |
209 | 0 | pack_store_ldac(p_ac->a_idsf[iqu], LDAC_IDSFBITS, p_stream, p_loc); |
210 | 0 | } |
211 | 0 | } |
212 | 0 | else { |
213 | 0 | pack_store_ldac(p_ac->sfc_offset, LDAC_IDSFBITS, p_stream, p_loc); |
214 | |
|
215 | 0 | pack_store_ldac(p_ac->sfc_weight, LDAC_SFCWTBLBITS, p_stream, p_loc); |
216 | |
|
217 | 0 | p_tbl = gaa_sfcwgt_ldac[p_ac->sfc_weight]; |
218 | 0 | for (iqu = 0; iqu < nqus; iqu++) { |
219 | 0 | pack_store_ldac(p_ac->a_idsf[iqu]+p_tbl[iqu]-p_ac->sfc_offset, p_ac->sfc_bitlen, p_stream, p_loc); |
220 | 0 | } |
221 | 0 | } |
222 | |
|
223 | 0 | return; |
224 | 0 | } |
225 | | |
226 | | /*************************************************************************************************** |
227 | | Subfunction: Pack Scale Factor Data - Mode 2 |
228 | | ***************************************************************************************************/ |
229 | | static void pack_scale_factor_2_ldac( |
230 | | AC *p_ac, |
231 | | STREAM *p_stream, |
232 | | int *p_loc) |
233 | 0 | { |
234 | 0 | HCENC *p_hcsf; |
235 | 0 | int iqu; |
236 | 0 | int nqus = p_ac->p_ab->nqus; |
237 | 0 | int dif; |
238 | |
|
239 | 0 | pack_store_ldac(p_ac->sfc_bitlen-LDAC_MINSFCBLEN_2, LDAC_SFCBLENBITS, p_stream, p_loc); |
240 | |
|
241 | 0 | p_hcsf = ga_hcenc_sf1_ldac + (p_ac->sfc_bitlen-LDAC_MINSFCBLEN_2); |
242 | 0 | for (iqu = 0; iqu < nqus; iqu++) { |
243 | 0 | dif = (p_ac->a_idsf[iqu] - p_ac->p_ab->ap_ac[0]->a_idsf[iqu]) & p_hcsf->mask; |
244 | 0 | pack_store_ldac(hc_word_ldac(p_hcsf->p_tbl+dif), hc_len_ldac(p_hcsf->p_tbl+dif), p_stream, p_loc); |
245 | 0 | } |
246 | |
|
247 | 0 | return; |
248 | 0 | } |
249 | | |
250 | | /*************************************************************************************************** |
251 | | Pack Scale Factor Data |
252 | | ***************************************************************************************************/ |
253 | | static void pack_scale_factor_ldac( |
254 | | AC *p_ac, |
255 | | STREAM *p_stream, |
256 | | int *p_loc) |
257 | 44 | { |
258 | 44 | int sfc_mode = p_ac->sfc_mode; |
259 | | |
260 | 44 | pack_store_ldac(sfc_mode, LDAC_SFCMODEBITS, p_stream, p_loc); |
261 | | |
262 | 44 | if (p_ac->ich == 0) { |
263 | 44 | if (sfc_mode == LDAC_MODE_0) { |
264 | 44 | pack_scale_factor_0_ldac(p_ac, p_stream, p_loc); |
265 | 44 | } |
266 | 0 | else { |
267 | 0 | pack_scale_factor_1_ldac(p_ac, p_stream, p_loc); |
268 | 0 | } |
269 | 44 | } |
270 | 0 | else { |
271 | 0 | if (sfc_mode == LDAC_MODE_0) { |
272 | 0 | pack_scale_factor_0_ldac(p_ac, p_stream, p_loc); |
273 | 0 | } |
274 | 0 | else { |
275 | 0 | pack_scale_factor_2_ldac(p_ac, p_stream, p_loc); |
276 | 0 | } |
277 | 0 | } |
278 | | |
279 | 44 | return; |
280 | 44 | } |
281 | | |
282 | | /*************************************************************************************************** |
283 | | Pack Spectrum Data |
284 | | ***************************************************************************************************/ |
285 | | static void pack_spectrum_ldac( |
286 | | AC *p_ac, |
287 | | STREAM *p_stream, |
288 | | int *p_loc) |
289 | 44 | { |
290 | 44 | int iqu, isp, i; |
291 | 44 | int lsp, hsp; |
292 | 44 | int nqus = p_ac->p_ab->nqus; |
293 | 44 | int nsps, idwl1, wl, val; |
294 | | |
295 | 1.18k | for (iqu = 0; iqu < nqus; iqu++) { |
296 | 1.14k | lsp = ga_isp_ldac[iqu]; |
297 | 1.14k | hsp = ga_isp_ldac[iqu+1]; |
298 | 1.14k | nsps = ga_nsps_ldac[iqu]; |
299 | 1.14k | idwl1 = p_ac->a_idwl1[iqu]; |
300 | 1.14k | wl = ga_wl_ldac[idwl1]; |
301 | | |
302 | 1.14k | if (idwl1 == 1) { |
303 | 66 | isp = lsp; |
304 | | |
305 | 66 | if (nsps == 2) { |
306 | 0 | val = (p_ac->a_qspec[isp ]+1) << 2; |
307 | 0 | val += (p_ac->a_qspec[isp+1]+1); |
308 | 0 | pack_store_ldac(ga_2dimenc_spec_ldac[val], LDAC_2DIMSPECBITS, p_stream, p_loc); |
309 | 0 | } |
310 | 66 | else { |
311 | 330 | for (i = 0; i < nsps>>2; i++, isp+=4) { |
312 | 264 | val = (p_ac->a_qspec[isp ]+1) << 6; |
313 | 264 | val += (p_ac->a_qspec[isp+1]+1) << 4; |
314 | 264 | val += (p_ac->a_qspec[isp+2]+1) << 2; |
315 | 264 | val += (p_ac->a_qspec[isp+3]+1); |
316 | 264 | pack_store_ldac(ga_4dimenc_spec_ldac[val], LDAC_4DIMSPECBITS, p_stream, p_loc); |
317 | 264 | } |
318 | 66 | } |
319 | 66 | } |
320 | 1.07k | else { |
321 | 5.65k | for (isp = lsp; isp < hsp; isp++) { |
322 | 4.57k | pack_store_ldac(p_ac->a_qspec[isp], wl, p_stream, p_loc); |
323 | 4.57k | } |
324 | 1.07k | } |
325 | 1.14k | } |
326 | | |
327 | 44 | return; |
328 | 44 | } |
329 | | |
330 | | /*************************************************************************************************** |
331 | | Pack Residual Data |
332 | | ***************************************************************************************************/ |
333 | | static void pack_residual_ldac( |
334 | | AC *p_ac, |
335 | | STREAM *p_stream, |
336 | | int *p_loc) |
337 | 44 | { |
338 | 44 | int iqu, isp; |
339 | 44 | int lsp, hsp; |
340 | 44 | int nqus = p_ac->p_ab->nqus; |
341 | 44 | int idwl2, wl; |
342 | | |
343 | 1.18k | for (iqu = 0; iqu < nqus; iqu++) { |
344 | 1.14k | idwl2 = p_ac->a_idwl2[iqu]; |
345 | | |
346 | 1.14k | if (idwl2 > 0) { |
347 | 0 | lsp = ga_isp_ldac[iqu]; |
348 | 0 | hsp = ga_isp_ldac[iqu+1]; |
349 | 0 | wl = ga_wl_ldac[idwl2]; |
350 | |
|
351 | 0 | for (isp = lsp; isp < hsp; isp++) { |
352 | 0 | pack_store_ldac(p_ac->a_rspec[isp], wl, p_stream, p_loc); |
353 | 0 | } |
354 | 0 | } |
355 | 1.14k | } |
356 | | |
357 | 44 | return; |
358 | 44 | } |
359 | | |
360 | | /*************************************************************************************************** |
361 | | Pack Audio Block |
362 | | ***************************************************************************************************/ |
363 | | static int pack_audio_block_ldac( |
364 | | AB *p_ab, |
365 | | STREAM *p_stream, |
366 | | int *p_loc) |
367 | 44 | { |
368 | 44 | AC *p_ac; |
369 | 44 | int ich; |
370 | 44 | int nchs = p_ab->blk_nchs; |
371 | 44 | int nbits_band, nbits_grad, a_nbits_scfc[2], a_nbits_spec[2], nbits_used; |
372 | 44 | int loc; |
373 | | |
374 | 132 | for (ich = 0; ich < 2; ich++) { |
375 | 88 | a_nbits_scfc[ich] = 0; |
376 | 88 | a_nbits_spec[ich] = 0; |
377 | 88 | } |
378 | | |
379 | 44 | loc = *p_loc; |
380 | 44 | pack_band_info_ldac(p_ab, p_stream, p_loc); |
381 | 44 | nbits_band = *p_loc - loc; |
382 | | |
383 | 44 | loc = *p_loc; |
384 | 44 | pack_gradient_ldac(p_ab, p_stream, p_loc); |
385 | 44 | nbits_grad = *p_loc - loc; |
386 | | |
387 | 44 | nbits_used = nbits_band + nbits_grad; |
388 | | |
389 | 88 | for (ich = 0; ich < nchs; ich++) { |
390 | 44 | p_ac = p_ab->ap_ac[ich]; |
391 | | |
392 | 44 | loc = *p_loc; |
393 | 44 | pack_scale_factor_ldac(p_ac, p_stream, p_loc); |
394 | 44 | a_nbits_scfc[ich] = *p_loc - loc; |
395 | | |
396 | 44 | loc = *p_loc; |
397 | 44 | pack_spectrum_ldac(p_ac, p_stream, p_loc); |
398 | 44 | a_nbits_spec[ich] = *p_loc - loc; |
399 | | |
400 | 44 | loc = *p_loc; |
401 | 44 | pack_residual_ldac(p_ac, p_stream, p_loc); |
402 | 44 | a_nbits_spec[ich] += *p_loc - loc; |
403 | | |
404 | 44 | nbits_used += a_nbits_scfc[ich] + a_nbits_spec[ich]; |
405 | 44 | } |
406 | | |
407 | 44 | if (nbits_used > p_ab->nbits_used) { |
408 | 0 | *p_ab->p_error_code = LDAC_ERR_BIT_PACKING; |
409 | 0 | return LDAC_FALSE; |
410 | 0 | } |
411 | 44 | else if (nbits_used < p_ab->nbits_used) { |
412 | 0 | *p_ab->p_error_code = LDAC_ERR_BIT_PACKING; |
413 | 0 | return LDAC_FALSE; |
414 | 0 | } |
415 | | |
416 | 44 | return LDAC_TRUE; |
417 | 44 | } |
418 | | |
419 | | /*************************************************************************************************** |
420 | | Pack Raw Data Frame |
421 | | ***************************************************************************************************/ |
422 | | DECLFUNC int pack_raw_data_frame_ldac( |
423 | | SFINFO *p_sfinfo, |
424 | | STREAM *p_stream, |
425 | | int *p_loc, |
426 | | int *p_nbytes_used) |
427 | 22 | { |
428 | 22 | CFG *p_cfg = &p_sfinfo->cfg; |
429 | 22 | AB *p_ab = p_sfinfo->p_ab; |
430 | 22 | int ibk; |
431 | 22 | int nbks = gaa_block_setting_ldac[p_cfg->chconfig_id][1]; |
432 | | |
433 | 66 | for (ibk = 0; ibk < nbks; ibk++) { |
434 | 44 | if (!pack_audio_block_ldac(p_ab, p_stream, p_loc)) { |
435 | 0 | return LDAC_ERR_PACK_BLOCK_FAILED; |
436 | 0 | } |
437 | | |
438 | 44 | pack_block_alignment_ldac(p_stream, p_loc); |
439 | | |
440 | 44 | p_ab++; |
441 | 44 | } |
442 | | |
443 | 22 | pack_frame_alignment_ldac(p_stream, p_loc, p_cfg->frame_length); |
444 | | |
445 | 22 | *p_nbytes_used = *p_loc / LDAC_BYTESIZE; |
446 | | |
447 | 22 | return LDAC_ERR_NONE; |
448 | 22 | } |
449 | | |
450 | | /*************************************************************************************************** |
451 | | Pack Null Data Frame |
452 | | ***************************************************************************************************/ |
453 | | static const int sa_null_data_size_ldac[2] = { |
454 | | 11, 15, |
455 | | }; |
456 | | static const STREAM saa_null_data_ldac[2][15] = { |
457 | | {0x07, 0xa0, 0x16, 0x00, 0x20, 0xad, 0x51, 0x45, 0x14, 0x50, 0x49}, |
458 | | {0x07, 0xa0, 0x0a, 0x00, 0x20, 0xad, 0x51, 0x41, 0x24, 0x93, 0x00, 0x28, 0xa0, 0x92, 0x49}, |
459 | | }; |
460 | | |
461 | | DECLFUNC int pack_null_data_frame_ldac( |
462 | | SFINFO *p_sfinfo, |
463 | | STREAM *p_stream, |
464 | | int *p_loc, |
465 | | int *p_nbytes_used) |
466 | 0 | { |
467 | 0 | CFG *p_cfg = &p_sfinfo->cfg; |
468 | 0 | AB *p_ab = p_sfinfo->p_ab; |
469 | 0 | int ibk; |
470 | 0 | int nbks = gaa_block_setting_ldac[p_cfg->chconfig_id][1]; |
471 | 0 | int blk_type, size, offset = 0; |
472 | |
|
473 | 0 | for (ibk = 0; ibk < nbks; ibk++) { |
474 | 0 | blk_type = p_ab->blk_type; |
475 | 0 | size = sa_null_data_size_ldac[blk_type]; |
476 | |
|
477 | 0 | copy_data_ldac(saa_null_data_ldac[blk_type], p_stream+offset, size*sizeof(STREAM)); |
478 | 0 | *p_loc += size*LDAC_BYTESIZE; |
479 | |
|
480 | 0 | offset += size; |
481 | 0 | p_ab++; |
482 | 0 | } |
483 | 0 | if (p_cfg->frame_length < offset) { |
484 | 0 | return LDAC_ERR_PACK_BLOCK_FAILED; |
485 | 0 | } |
486 | | |
487 | 0 | pack_frame_alignment_ldac(p_stream, p_loc, p_cfg->frame_length); |
488 | |
|
489 | 0 | *p_nbytes_used = *p_loc / LDAC_BYTESIZE; |
490 | |
|
491 | 0 | return LDAC_ERR_NONE; |
492 | 0 | } |
493 | | |