## ffmpeg / libavcodec / mjpegenc.c @ d771bcae

History | View | Annotate | Download (12.8 KB)

1 | de6d9b64 | Fabrice Bellard | ```
/*
``` |
---|---|---|---|

2 | ```
* MJPEG encoder
``` |
||

3 | ```
* Copyright (c) 2000 Gerard Lantau.
``` |
||

4 | ```
*
``` |
||

5 | ```
* This program is free software; you can redistribute it and/or modify
``` |
||

6 | ```
* it under the terms of the GNU General Public License as published by
``` |
||

7 | ```
* the Free Software Foundation; either version 2 of the License, or
``` |
||

8 | ```
* (at your option) any later version.
``` |
||

9 | ```
*
``` |
||

10 | ```
* This program is distributed in the hope that it will be useful,
``` |
||

11 | ```
* but WITHOUT ANY WARRANTY; without even the implied warranty of
``` |
||

12 | ```
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
``` |
||

13 | ```
* GNU General Public License for more details.
``` |
||

14 | ```
*
``` |
||

15 | ```
* You should have received a copy of the GNU General Public License
``` |
||

16 | ```
* along with this program; if not, write to the Free Software
``` |
||

17 | ```
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
``` |
||

18 | ```
*/
``` |
||

19 | #include <stdlib.h> |
||

20 | #include <stdio.h> |
||

21 | #include "avcodec.h" |
||

22 | #include "dsputil.h" |
||

23 | #include "mpegvideo.h" |
||

24 | |||

25 | typedef struct MJpegContext { |
||

26 | ```
UINT8 huff_size_dc_luminance[12];
``` |
||

27 | ```
UINT16 huff_code_dc_luminance[12];
``` |
||

28 | ```
UINT8 huff_size_dc_chrominance[12];
``` |
||

29 | ```
UINT16 huff_code_dc_chrominance[12];
``` |
||

30 | |||

31 | ```
UINT8 huff_size_ac_luminance[256];
``` |
||

32 | ```
UINT16 huff_code_ac_luminance[256];
``` |
||

33 | ```
UINT8 huff_size_ac_chrominance[256];
``` |
||

34 | ```
UINT16 huff_code_ac_chrominance[256];
``` |
||

35 | } MJpegContext; |
||

36 | |||

37 | #define SOF0 0xc0 |
||

38 | #define SOI 0xd8 |
||

39 | #define EOI 0xd9 |
||

40 | #define DQT 0xdb |
||

41 | #define DHT 0xc4 |
||

42 | #define SOS 0xda |
||

43 | |||

44 | ```
#if 0
``` |
||

45 | ```
/* These are the sample quantization tables given in JPEG spec section K.1.
``` |
||

46 | ```
* The spec says that the values given produce "good" quality, and
``` |
||

47 | ```
* when divided by 2, "very good" quality.
``` |
||

48 | ```
*/
``` |
||

49 | ```
static const unsigned char std_luminance_quant_tbl[64] = {
``` |
||

50 | ```
16, 11, 10, 16, 24, 40, 51, 61,
``` |
||

51 | ```
12, 12, 14, 19, 26, 58, 60, 55,
``` |
||

52 | ```
14, 13, 16, 24, 40, 57, 69, 56,
``` |
||

53 | ```
14, 17, 22, 29, 51, 87, 80, 62,
``` |
||

54 | ```
18, 22, 37, 56, 68, 109, 103, 77,
``` |
||

55 | ```
24, 35, 55, 64, 81, 104, 113, 92,
``` |
||

56 | ```
49, 64, 78, 87, 103, 121, 120, 101,
``` |
||

57 | ```
72, 92, 95, 98, 112, 100, 103, 99
``` |
||

58 | ```
};
``` |
||

59 | ```
static const unsigned char std_chrominance_quant_tbl[64] = {
``` |
||

60 | ```
17, 18, 24, 47, 99, 99, 99, 99,
``` |
||

61 | ```
18, 21, 26, 66, 99, 99, 99, 99,
``` |
||

62 | ```
24, 26, 56, 99, 99, 99, 99, 99,
``` |
||

63 | ```
47, 66, 99, 99, 99, 99, 99, 99,
``` |
||

64 | ```
99, 99, 99, 99, 99, 99, 99, 99,
``` |
||

65 | ```
99, 99, 99, 99, 99, 99, 99, 99,
``` |
||

66 | ```
99, 99, 99, 99, 99, 99, 99, 99,
``` |
||

67 | ```
99, 99, 99, 99, 99, 99, 99, 99
``` |
||

68 | ```
};
``` |
||

69 | ```
#endif
``` |
||

70 | |||

71 | ```
/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
``` |
||

72 | ```
/* IMPORTANT: these are only valid for 8-bit data precision! */
``` |
||

73 | static const UINT8 bits_dc_luminance[17] = |
||

74 | { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; |
||

75 | static const UINT8 val_dc_luminance[] = |
||

76 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; |
||

77 | |||

78 | static const UINT8 bits_dc_chrominance[17] = |
||

79 | { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; |
||

80 | static const UINT8 val_dc_chrominance[] = |
||

81 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; |
||

82 | |||

83 | static const UINT8 bits_ac_luminance[17] = |
||

84 | { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; |
||

85 | static const UINT8 val_ac_luminance[] = |
||

86 | { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, |
||

87 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, |
||

88 | 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, |
||

89 | 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, |
||

90 | 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, |
||

91 | 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, |
||

92 | 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, |
||

93 | 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, |
||

94 | 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, |
||

95 | 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, |
||

96 | 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, |
||

97 | 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, |
||

98 | 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, |
||

99 | 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, |
||

100 | 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, |
||

101 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, |
||

102 | 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, |
||

103 | 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, |
||

104 | 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, |
||

105 | 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
||

106 | 0xf9, 0xfa |
||

107 | }; |
||

108 | |||

109 | static const UINT8 bits_ac_chrominance[17] = |
||

110 | { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; |
||

111 | |||

112 | static const UINT8 val_ac_chrominance[] = |
||

113 | { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, |
||

114 | 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, |
||

115 | 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, |
||

116 | 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, |
||

117 | 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, |
||

118 | 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, |
||

119 | 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, |
||

120 | 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, |
||

121 | 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, |
||

122 | 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, |
||

123 | 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, |
||

124 | 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, |
||

125 | 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, |
||

126 | 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, |
||

127 | 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, |
||

128 | 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, |
||

129 | 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, |
||

130 | 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, |
||

131 | 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, |
||

132 | 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
||

133 | 0xf9, 0xfa |
||

134 | }; |
||

135 | |||

136 | |||

137 | ```
/* isn't this function nicer than the one in the libjpeg ? */
``` |
||

138 | static void build_huffman_codes(UINT8 *huff_size, UINT16 *huff_code, |
||

139 | const UINT8 *bits_table, const UINT8 *val_table) |
||

140 | { |
||

141 | ```
int i, j, k,nb, code, sym;
``` |
||

142 | |||

143 | ```
code = 0;
``` |
||

144 | ```
k = 0;
``` |
||

145 | for(i=1;i<=16;i++) { |
||

146 | nb = bits_table[i]; |
||

147 | for(j=0;j<nb;j++) { |
||

148 | sym = val_table[k++]; |
||

149 | huff_size[sym] = i; |
||

150 | huff_code[sym] = code; |
||

151 | code++; |
||

152 | } |
||

153 | ```
code <<= 1;
``` |
||

154 | } |
||

155 | } |
||

156 | |||

157 | ```
int mjpeg_init(MpegEncContext *s)
``` |
||

158 | { |
||

159 | MJpegContext *m; |
||

160 | |||

161 | ```
m = malloc(sizeof(MJpegContext));
``` |
||

162 | ```
if (!m)
``` |
||

163 | return -1; |
||

164 | |||

165 | ```
/* build all the huffman tables */
``` |
||

166 | build_huffman_codes(m->huff_size_dc_luminance, |
||

167 | m->huff_code_dc_luminance, |
||

168 | bits_dc_luminance, |
||

169 | val_dc_luminance); |
||

170 | build_huffman_codes(m->huff_size_dc_chrominance, |
||

171 | m->huff_code_dc_chrominance, |
||

172 | bits_dc_chrominance, |
||

173 | val_dc_chrominance); |
||

174 | build_huffman_codes(m->huff_size_ac_luminance, |
||

175 | m->huff_code_ac_luminance, |
||

176 | bits_ac_luminance, |
||

177 | val_ac_luminance); |
||

178 | build_huffman_codes(m->huff_size_ac_chrominance, |
||

179 | m->huff_code_ac_chrominance, |
||

180 | bits_ac_chrominance, |
||

181 | val_ac_chrominance); |
||

182 | |||

183 | s->mjpeg_ctx = m; |
||

184 | return 0; |
||

185 | } |
||

186 | |||

187 | ```
void mjpeg_close(MpegEncContext *s)
``` |
||

188 | { |
||

189 | free(s->mjpeg_ctx); |
||

190 | } |
||

191 | |||

192 | static inline void put_marker(PutBitContext *p, int code) |
||

193 | { |
||

194 | put_bits(p, 8, 0xff); |
||

195 | ```
put_bits(p, 8, code);
``` |
||

196 | } |
||

197 | |||

198 | ```
/* table_class: 0 = DC coef, 1 = AC coefs */
``` |
||

199 | static int put_huffman_table(MpegEncContext *s, int table_class, int table_id, |
||

200 | const UINT8 *bits_table, const UINT8 *value_table) |
||

201 | { |
||

202 | PutBitContext *p = &s->pb; |
||

203 | ```
int n, i;
``` |
||

204 | |||

205 | ```
put_bits(p, 4, table_class);
``` |
||

206 | ```
put_bits(p, 4, table_id);
``` |
||

207 | |||

208 | ```
n = 0;
``` |
||

209 | for(i=1;i<=16;i++) { |
||

210 | n += bits_table[i]; |
||

211 | ```
put_bits(p, 8, bits_table[i]);
``` |
||

212 | } |
||

213 | |||

214 | for(i=0;i<n;i++) |
||

215 | ```
put_bits(p, 8, value_table[i]);
``` |
||

216 | |||

217 | return n + 17; |
||

218 | } |
||

219 | |||

220 | static void jpeg_table_header(MpegEncContext *s) |
||

221 | { |
||

222 | PutBitContext *p = &s->pb; |
||

223 | ```
int i, size;
``` |
||

224 | UINT8 *ptr; |
||

225 | |||

226 | ```
/* quant matrixes */
``` |
||

227 | put_marker(p, DQT); |
||

228 | put_bits(p, 16, 2 + 1 * (1 + 64)); |
||

229 | put_bits(p, 4, 0); /* 8 bit precision */ |
||

230 | put_bits(p, 4, 0); /* table 0 */ |
||

231 | for(i=0;i<64;i++) { |
||

232 | ```
put_bits(p, 8, s->intra_matrix[i]);
``` |
||

233 | } |
||

234 | ```
#if 0
``` |
||

235 | ```
put_bits(p, 4, 0); /* 8 bit precision */
``` |
||

236 | ```
put_bits(p, 4, 1); /* table 1 */
``` |
||

237 | ```
for(i=0;i<64;i++) {
``` |
||

238 | ```
put_bits(p, 8, s->chroma_intra_matrix[i]);
``` |
||

239 | ```
}
``` |
||

240 | ```
#endif
``` |
||

241 | |||

242 | ```
/* huffman table */
``` |
||

243 | put_marker(p, DHT); |
||

244 | flush_put_bits(p); |
||

245 | ptr = p->buf_ptr; |
||

246 | put_bits(p, 16, 0); /* patched later */ |
||

247 | ```
size = 2;
``` |
||

248 | size += put_huffman_table(s, 0, 0, bits_dc_luminance, val_dc_luminance); |
||

249 | size += put_huffman_table(s, 0, 1, bits_dc_chrominance, val_dc_chrominance); |
||

250 | |||

251 | size += put_huffman_table(s, 1, 0, bits_ac_luminance, val_ac_luminance); |
||

252 | size += put_huffman_table(s, 1, 1, bits_ac_chrominance, val_ac_chrominance); |
||

253 | ptr[0] = size >> 8; |
||

254 | ```
ptr[1] = size;
``` |
||

255 | } |
||

256 | |||

257 | ```
void mjpeg_picture_header(MpegEncContext *s)
``` |
||

258 | { |
||

259 | put_marker(&s->pb, SOI); |
||

260 | |||

261 | jpeg_table_header(s); |
||

262 | |||

263 | put_marker(&s->pb, SOF0); |
||

264 | |||

265 | put_bits(&s->pb, 16, 17); |
||

266 | put_bits(&s->pb, 8, 8); /* 8 bits/component */ |
||

267 | ```
put_bits(&s->pb, 16, s->height);
``` |
||

268 | ```
put_bits(&s->pb, 16, s->width);
``` |
||

269 | put_bits(&s->pb, 8, 3); /* 3 components */ |
||

270 | |||

271 | ```
/* Y component */
``` |
||

272 | put_bits(&s->pb, 8, 1); /* component number */ |
||

273 | put_bits(&s->pb, 4, 2); /* H factor */ |
||

274 | put_bits(&s->pb, 4, 2); /* V factor */ |
||

275 | put_bits(&s->pb, 8, 0); /* select matrix */ |
||

276 | |||

277 | ```
/* Cb component */
``` |
||

278 | put_bits(&s->pb, 8, 2); /* component number */ |
||

279 | put_bits(&s->pb, 4, 1); /* H factor */ |
||

280 | put_bits(&s->pb, 4, 1); /* V factor */ |
||

281 | put_bits(&s->pb, 8, 0); /* select matrix */ |
||

282 | |||

283 | ```
/* Cr component */
``` |
||

284 | put_bits(&s->pb, 8, 3); /* component number */ |
||

285 | put_bits(&s->pb, 4, 1); /* H factor */ |
||

286 | put_bits(&s->pb, 4, 1); /* V factor */ |
||

287 | put_bits(&s->pb, 8, 0); /* select matrix */ |
||

288 | |||

289 | ```
/* scan header */
``` |
||

290 | put_marker(&s->pb, SOS); |
||

291 | put_bits(&s->pb, 16, 12); /* length */ |
||

292 | put_bits(&s->pb, 8, 3); /* 3 components */ |
||

293 | |||

294 | ```
/* Y component */
``` |
||

295 | put_bits(&s->pb, 8, 1); /* index */ |
||

296 | put_bits(&s->pb, 4, 0); /* DC huffman table index */ |
||

297 | put_bits(&s->pb, 4, 0); /* AC huffman table index */ |
||

298 | |||

299 | ```
/* Cb component */
``` |
||

300 | put_bits(&s->pb, 8, 2); /* index */ |
||

301 | put_bits(&s->pb, 4, 1); /* DC huffman table index */ |
||

302 | put_bits(&s->pb, 4, 1); /* AC huffman table index */ |
||

303 | |||

304 | ```
/* Cr component */
``` |
||

305 | put_bits(&s->pb, 8, 3); /* index */ |
||

306 | put_bits(&s->pb, 4, 1); /* DC huffman table index */ |
||

307 | put_bits(&s->pb, 4, 1); /* AC huffman table index */ |
||

308 | |||

309 | put_bits(&s->pb, 8, 0); /* Ss (not used) */ |
||

310 | put_bits(&s->pb, 8, 63); /* Se (not used) */ |
||

311 | put_bits(&s->pb, 8, 0); /* (not used) */ |
||

312 | } |
||

313 | |||

314 | ```
void mjpeg_picture_trailer(MpegEncContext *s)
``` |
||

315 | { |
||

316 | jflush_put_bits(&s->pb); |
||

317 | put_marker(&s->pb, EOI); |
||

318 | } |
||

319 | |||

320 | static inline void encode_dc(MpegEncContext *s, int val, |
||

321 | UINT8 *huff_size, UINT16 *huff_code) |
||

322 | { |
||

323 | ```
int mant, nbits;
``` |
||

324 | |||

325 | if (val == 0) { |
||

326 | jput_bits(&s->pb, huff_size[0], huff_code[0]); |
||

327 | ```
} else {
``` |
||

328 | mant = val; |
||

329 | if (val < 0) { |
||

330 | val = -val; |
||

331 | mant--; |
||

332 | } |
||

333 | |||

334 | ```
/* compute the log (XXX: optimize) */
``` |
||

335 | ```
nbits = 0;
``` |
||

336 | while (val != 0) { |
||

337 | ```
val = val >> 1;
``` |
||

338 | nbits++; |
||

339 | } |
||

340 | |||

341 | jput_bits(&s->pb, huff_size[nbits], huff_code[nbits]); |
||

342 | |||

343 | jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); |
||

344 | } |
||

345 | } |
||

346 | |||

347 | static void encode_block(MpegEncContext *s, DCTELEM *block, int n) |
||

348 | { |
||

349 | ```
int mant, nbits, code, i, j;
``` |
||

350 | ```
int component, dc, run, last_index, val;
``` |
||

351 | MJpegContext *m = s->mjpeg_ctx; |
||

352 | UINT8 *huff_size_ac; |
||

353 | UINT16 *huff_code_ac; |
||

354 | |||

355 | ```
/* DC coef */
``` |
||

356 | component = (n <= 3 ? 0 : n - 4 + 1); |
||

357 | dc = block[0]; /* overflow is impossible */ |
||

358 | val = dc - s->last_dc[component]; |
||

359 | if (n < 4) { |
||

360 | encode_dc(s, val, m->huff_size_dc_luminance, m->huff_code_dc_luminance); |
||

361 | huff_size_ac = m->huff_size_ac_luminance; |
||

362 | huff_code_ac = m->huff_code_ac_luminance; |
||

363 | ```
} else {
``` |
||

364 | encode_dc(s, val, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); |
||

365 | huff_size_ac = m->huff_size_ac_chrominance; |
||

366 | huff_code_ac = m->huff_code_ac_chrominance; |
||

367 | } |
||

368 | s->last_dc[component] = dc; |
||

369 | |||

370 | ```
/* AC coefs */
``` |
||

371 | |||

372 | ```
run = 0;
``` |
||

373 | last_index = s->block_last_index[n]; |
||

374 | for(i=1;i<=last_index;i++) { |
||

375 | j = zigzag_direct[i]; |
||

376 | val = block[j]; |
||

377 | if (val == 0) { |
||

378 | run++; |
||

379 | ```
} else {
``` |
||

380 | while (run >= 16) { |
||

381 | jput_bits(&s->pb, huff_size_ac[0xf0], huff_code_ac[0xf0]); |
||

382 | ```
run -= 16;
``` |
||

383 | } |
||

384 | mant = val; |
||

385 | if (val < 0) { |
||

386 | val = -val; |
||

387 | mant--; |
||

388 | } |
||

389 | |||

390 | ```
/* compute the log (XXX: optimize) */
``` |
||

391 | ```
nbits = 0;
``` |
||

392 | while (val != 0) { |
||

393 | ```
val = val >> 1;
``` |
||

394 | nbits++; |
||

395 | } |
||

396 | ```
code = (run << 4) | nbits;
``` |
||

397 | |||

398 | jput_bits(&s->pb, huff_size_ac[code], huff_code_ac[code]); |
||

399 | |||

400 | jput_bits(&s->pb, nbits, mant & ((1 << nbits) - 1)); |
||

401 | ```
run = 0;
``` |
||

402 | } |
||

403 | } |
||

404 | |||

405 | ```
/* output EOB only if not already 64 values */
``` |
||

406 | if (last_index < 63 || run != 0) |
||

407 | jput_bits(&s->pb, huff_size_ac[0], huff_code_ac[0]); |
||

408 | } |
||

409 | |||

410 | ```
void mjpeg_encode_mb(MpegEncContext *s,
``` |
||

411 | DCTELEM block[6][64]) |
||

412 | { |
||

413 | ```
int i;
``` |
||

414 | for(i=0;i<6;i++) { |
||

415 | encode_block(s, block[i], i); |
||

416 | } |
||

417 | } |