annotate ffmpeg/libavcodec/ppc/h264_qpel.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Copyright (c) 2004 Romain Dolbeau <romain@dolbeau.org>
yading@10 3 *
yading@10 4 * This file is part of FFmpeg.
yading@10 5 *
yading@10 6 * FFmpeg is free software; you can redistribute it and/or
yading@10 7 * modify it under the terms of the GNU Lesser General Public
yading@10 8 * License as published by the Free Software Foundation; either
yading@10 9 * version 2.1 of the License, or (at your option) any later version.
yading@10 10 *
yading@10 11 * FFmpeg is distributed in the hope that it will be useful,
yading@10 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 14 * Lesser General Public License for more details.
yading@10 15 *
yading@10 16 * You should have received a copy of the GNU Lesser General Public
yading@10 17 * License along with FFmpeg; if not, write to the Free Software
yading@10 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 19 */
yading@10 20
yading@10 21 #include "config.h"
yading@10 22 #include "libavutil/attributes.h"
yading@10 23 #include "libavcodec/h264qpel.h"
yading@10 24
yading@10 25 #if HAVE_ALTIVEC
yading@10 26 #include "libavutil/cpu.h"
yading@10 27 #include "libavutil/intreadwrite.h"
yading@10 28 #include "libavutil/ppc/types_altivec.h"
yading@10 29 #include "libavutil/ppc/util_altivec.h"
yading@10 30 #include "dsputil_altivec.h"
yading@10 31
yading@10 32 #define PUT_OP_U8_ALTIVEC(d, s, dst) d = s
yading@10 33 #define AVG_OP_U8_ALTIVEC(d, s, dst) d = vec_avg(dst, s)
yading@10 34
yading@10 35 #define OP_U8_ALTIVEC PUT_OP_U8_ALTIVEC
yading@10 36 #define PREFIX_h264_qpel16_h_lowpass_altivec put_h264_qpel16_h_lowpass_altivec
yading@10 37 #define PREFIX_h264_qpel16_h_lowpass_num altivec_put_h264_qpel16_h_lowpass_num
yading@10 38 #define PREFIX_h264_qpel16_v_lowpass_altivec put_h264_qpel16_v_lowpass_altivec
yading@10 39 #define PREFIX_h264_qpel16_v_lowpass_num altivec_put_h264_qpel16_v_lowpass_num
yading@10 40 #define PREFIX_h264_qpel16_hv_lowpass_altivec put_h264_qpel16_hv_lowpass_altivec
yading@10 41 #define PREFIX_h264_qpel16_hv_lowpass_num altivec_put_h264_qpel16_hv_lowpass_num
yading@10 42 #include "h264_qpel_template.c"
yading@10 43 #undef OP_U8_ALTIVEC
yading@10 44 #undef PREFIX_h264_qpel16_h_lowpass_altivec
yading@10 45 #undef PREFIX_h264_qpel16_h_lowpass_num
yading@10 46 #undef PREFIX_h264_qpel16_v_lowpass_altivec
yading@10 47 #undef PREFIX_h264_qpel16_v_lowpass_num
yading@10 48 #undef PREFIX_h264_qpel16_hv_lowpass_altivec
yading@10 49 #undef PREFIX_h264_qpel16_hv_lowpass_num
yading@10 50
yading@10 51 #define OP_U8_ALTIVEC AVG_OP_U8_ALTIVEC
yading@10 52 #define PREFIX_h264_qpel16_h_lowpass_altivec avg_h264_qpel16_h_lowpass_altivec
yading@10 53 #define PREFIX_h264_qpel16_h_lowpass_num altivec_avg_h264_qpel16_h_lowpass_num
yading@10 54 #define PREFIX_h264_qpel16_v_lowpass_altivec avg_h264_qpel16_v_lowpass_altivec
yading@10 55 #define PREFIX_h264_qpel16_v_lowpass_num altivec_avg_h264_qpel16_v_lowpass_num
yading@10 56 #define PREFIX_h264_qpel16_hv_lowpass_altivec avg_h264_qpel16_hv_lowpass_altivec
yading@10 57 #define PREFIX_h264_qpel16_hv_lowpass_num altivec_avg_h264_qpel16_hv_lowpass_num
yading@10 58 #include "h264_qpel_template.c"
yading@10 59 #undef OP_U8_ALTIVEC
yading@10 60 #undef PREFIX_h264_qpel16_h_lowpass_altivec
yading@10 61 #undef PREFIX_h264_qpel16_h_lowpass_num
yading@10 62 #undef PREFIX_h264_qpel16_v_lowpass_altivec
yading@10 63 #undef PREFIX_h264_qpel16_v_lowpass_num
yading@10 64 #undef PREFIX_h264_qpel16_hv_lowpass_altivec
yading@10 65 #undef PREFIX_h264_qpel16_hv_lowpass_num
yading@10 66
yading@10 67 #define H264_MC(OPNAME, SIZE, CODETYPE) \
yading@10 68 static void OPNAME ## h264_qpel ## SIZE ## _mc00_ ## CODETYPE (uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 69 {\
yading@10 70 ff_ ## OPNAME ## pixels ## SIZE ## _ ## CODETYPE(dst, src, stride, SIZE);\
yading@10 71 }\
yading@10 72 \
yading@10 73 static void OPNAME ## h264_qpel ## SIZE ## _mc10_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 74 { \
yading@10 75 DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\
yading@10 76 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(half, src, SIZE, stride);\
yading@10 77 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src, half, stride, stride, SIZE);\
yading@10 78 }\
yading@10 79 \
yading@10 80 static void OPNAME ## h264_qpel ## SIZE ## _mc20_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 81 {\
yading@10 82 OPNAME ## h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(dst, src, stride, stride);\
yading@10 83 }\
yading@10 84 \
yading@10 85 static void OPNAME ## h264_qpel ## SIZE ## _mc30_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 86 {\
yading@10 87 DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\
yading@10 88 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(half, src, SIZE, stride);\
yading@10 89 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src+1, half, stride, stride, SIZE);\
yading@10 90 }\
yading@10 91 \
yading@10 92 static void OPNAME ## h264_qpel ## SIZE ## _mc01_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 93 {\
yading@10 94 DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\
yading@10 95 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(half, src, SIZE, stride);\
yading@10 96 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src, half, stride, stride, SIZE);\
yading@10 97 }\
yading@10 98 \
yading@10 99 static void OPNAME ## h264_qpel ## SIZE ## _mc02_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 100 {\
yading@10 101 OPNAME ## h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(dst, src, stride, stride);\
yading@10 102 }\
yading@10 103 \
yading@10 104 static void OPNAME ## h264_qpel ## SIZE ## _mc03_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 105 {\
yading@10 106 DECLARE_ALIGNED(16, uint8_t, half)[SIZE*SIZE];\
yading@10 107 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(half, src, SIZE, stride);\
yading@10 108 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, src+stride, half, stride, stride, SIZE);\
yading@10 109 }\
yading@10 110 \
yading@10 111 static void OPNAME ## h264_qpel ## SIZE ## _mc11_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 112 {\
yading@10 113 DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\
yading@10 114 DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\
yading@10 115 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src, SIZE, stride);\
yading@10 116 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src, SIZE, stride);\
yading@10 117 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\
yading@10 118 }\
yading@10 119 \
yading@10 120 static void OPNAME ## h264_qpel ## SIZE ## _mc31_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 121 {\
yading@10 122 DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\
yading@10 123 DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\
yading@10 124 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src, SIZE, stride);\
yading@10 125 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src+1, SIZE, stride);\
yading@10 126 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\
yading@10 127 }\
yading@10 128 \
yading@10 129 static void OPNAME ## h264_qpel ## SIZE ## _mc13_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 130 {\
yading@10 131 DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\
yading@10 132 DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\
yading@10 133 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src + stride, SIZE, stride);\
yading@10 134 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src, SIZE, stride);\
yading@10 135 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\
yading@10 136 }\
yading@10 137 \
yading@10 138 static void OPNAME ## h264_qpel ## SIZE ## _mc33_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 139 {\
yading@10 140 DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\
yading@10 141 DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\
yading@10 142 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src + stride, SIZE, stride);\
yading@10 143 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src+1, SIZE, stride);\
yading@10 144 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfV, stride, SIZE, SIZE);\
yading@10 145 }\
yading@10 146 \
yading@10 147 static void OPNAME ## h264_qpel ## SIZE ## _mc22_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 148 {\
yading@10 149 DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\
yading@10 150 OPNAME ## h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(dst, tmp, src, stride, SIZE, stride);\
yading@10 151 }\
yading@10 152 \
yading@10 153 static void OPNAME ## h264_qpel ## SIZE ## _mc21_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 154 {\
yading@10 155 DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\
yading@10 156 DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\
yading@10 157 DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\
yading@10 158 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src, SIZE, stride);\
yading@10 159 put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\
yading@10 160 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfHV, stride, SIZE, SIZE);\
yading@10 161 }\
yading@10 162 \
yading@10 163 static void OPNAME ## h264_qpel ## SIZE ## _mc23_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 164 {\
yading@10 165 DECLARE_ALIGNED(16, uint8_t, halfH)[SIZE*SIZE];\
yading@10 166 DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\
yading@10 167 DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\
yading@10 168 put_h264_qpel ## SIZE ## _h_lowpass_ ## CODETYPE(halfH, src + stride, SIZE, stride);\
yading@10 169 put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\
yading@10 170 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfH, halfHV, stride, SIZE, SIZE);\
yading@10 171 }\
yading@10 172 \
yading@10 173 static void OPNAME ## h264_qpel ## SIZE ## _mc12_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 174 {\
yading@10 175 DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\
yading@10 176 DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\
yading@10 177 DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\
yading@10 178 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src, SIZE, stride);\
yading@10 179 put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\
yading@10 180 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfV, halfHV, stride, SIZE, SIZE);\
yading@10 181 }\
yading@10 182 \
yading@10 183 static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## CODETYPE(uint8_t *dst, uint8_t *src, ptrdiff_t stride)\
yading@10 184 {\
yading@10 185 DECLARE_ALIGNED(16, uint8_t, halfV)[SIZE*SIZE];\
yading@10 186 DECLARE_ALIGNED(16, uint8_t, halfHV)[SIZE*SIZE];\
yading@10 187 DECLARE_ALIGNED(16, int16_t, tmp)[SIZE*(SIZE+8)];\
yading@10 188 put_h264_qpel ## SIZE ## _v_lowpass_ ## CODETYPE(halfV, src+1, SIZE, stride);\
yading@10 189 put_h264_qpel ## SIZE ## _hv_lowpass_ ## CODETYPE(halfHV, tmp, src, SIZE, SIZE, stride);\
yading@10 190 OPNAME ## pixels ## SIZE ## _l2_ ## CODETYPE(dst, halfV, halfHV, stride, SIZE, SIZE);\
yading@10 191 }\
yading@10 192
yading@10 193 static inline void put_pixels16_l2_altivec( uint8_t * dst, const uint8_t * src1,
yading@10 194 const uint8_t * src2, int dst_stride,
yading@10 195 int src_stride1, int h)
yading@10 196 {
yading@10 197 int i;
yading@10 198 vec_u8 a, b, d, tmp1, tmp2, mask, mask_, edges, align;
yading@10 199
yading@10 200 mask_ = vec_lvsl(0, src2);
yading@10 201
yading@10 202 for (i = 0; i < h; i++) {
yading@10 203
yading@10 204 tmp1 = vec_ld(i * src_stride1, src1);
yading@10 205 mask = vec_lvsl(i * src_stride1, src1);
yading@10 206 tmp2 = vec_ld(i * src_stride1 + 15, src1);
yading@10 207
yading@10 208 a = vec_perm(tmp1, tmp2, mask);
yading@10 209
yading@10 210 tmp1 = vec_ld(i * 16, src2);
yading@10 211 tmp2 = vec_ld(i * 16 + 15, src2);
yading@10 212
yading@10 213 b = vec_perm(tmp1, tmp2, mask_);
yading@10 214
yading@10 215 tmp1 = vec_ld(0, dst);
yading@10 216 mask = vec_lvsl(0, dst);
yading@10 217 tmp2 = vec_ld(15, dst);
yading@10 218
yading@10 219 d = vec_avg(a, b);
yading@10 220
yading@10 221 edges = vec_perm(tmp2, tmp1, mask);
yading@10 222
yading@10 223 align = vec_lvsr(0, dst);
yading@10 224
yading@10 225 tmp2 = vec_perm(d, edges, align);
yading@10 226 tmp1 = vec_perm(edges, d, align);
yading@10 227
yading@10 228 vec_st(tmp2, 15, dst);
yading@10 229 vec_st(tmp1, 0 , dst);
yading@10 230
yading@10 231 dst += dst_stride;
yading@10 232 }
yading@10 233 }
yading@10 234
yading@10 235 static inline void avg_pixels16_l2_altivec( uint8_t * dst, const uint8_t * src1,
yading@10 236 const uint8_t * src2, int dst_stride,
yading@10 237 int src_stride1, int h)
yading@10 238 {
yading@10 239 int i;
yading@10 240 vec_u8 a, b, d, tmp1, tmp2, mask, mask_, edges, align;
yading@10 241
yading@10 242 mask_ = vec_lvsl(0, src2);
yading@10 243
yading@10 244 for (i = 0; i < h; i++) {
yading@10 245
yading@10 246 tmp1 = vec_ld(i * src_stride1, src1);
yading@10 247 mask = vec_lvsl(i * src_stride1, src1);
yading@10 248 tmp2 = vec_ld(i * src_stride1 + 15, src1);
yading@10 249
yading@10 250 a = vec_perm(tmp1, tmp2, mask);
yading@10 251
yading@10 252 tmp1 = vec_ld(i * 16, src2);
yading@10 253 tmp2 = vec_ld(i * 16 + 15, src2);
yading@10 254
yading@10 255 b = vec_perm(tmp1, tmp2, mask_);
yading@10 256
yading@10 257 tmp1 = vec_ld(0, dst);
yading@10 258 mask = vec_lvsl(0, dst);
yading@10 259 tmp2 = vec_ld(15, dst);
yading@10 260
yading@10 261 d = vec_avg(vec_perm(tmp1, tmp2, mask), vec_avg(a, b));
yading@10 262
yading@10 263 edges = vec_perm(tmp2, tmp1, mask);
yading@10 264
yading@10 265 align = vec_lvsr(0, dst);
yading@10 266
yading@10 267 tmp2 = vec_perm(d, edges, align);
yading@10 268 tmp1 = vec_perm(edges, d, align);
yading@10 269
yading@10 270 vec_st(tmp2, 15, dst);
yading@10 271 vec_st(tmp1, 0 , dst);
yading@10 272
yading@10 273 dst += dst_stride;
yading@10 274 }
yading@10 275 }
yading@10 276
yading@10 277 /* Implemented but could be faster
yading@10 278 #define put_pixels16_l2_altivec(d,s1,s2,ds,s1s,h) put_pixels16_l2(d,s1,s2,ds,s1s,16,h)
yading@10 279 #define avg_pixels16_l2_altivec(d,s1,s2,ds,s1s,h) avg_pixels16_l2(d,s1,s2,ds,s1s,16,h)
yading@10 280 */
yading@10 281
yading@10 282 H264_MC(put_, 16, altivec)
yading@10 283 H264_MC(avg_, 16, altivec)
yading@10 284 #endif /* HAVE_ALTIVEC */
yading@10 285
yading@10 286 av_cold void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth)
yading@10 287 {
yading@10 288 #if HAVE_ALTIVEC
yading@10 289 const int high_bit_depth = bit_depth > 8;
yading@10 290
yading@10 291 if (av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC) {
yading@10 292 if (!high_bit_depth) {
yading@10 293 #define dspfunc(PFX, IDX, NUM) \
yading@10 294 c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_altivec; \
yading@10 295 c->PFX ## _pixels_tab[IDX][ 1] = PFX ## NUM ## _mc10_altivec; \
yading@10 296 c->PFX ## _pixels_tab[IDX][ 2] = PFX ## NUM ## _mc20_altivec; \
yading@10 297 c->PFX ## _pixels_tab[IDX][ 3] = PFX ## NUM ## _mc30_altivec; \
yading@10 298 c->PFX ## _pixels_tab[IDX][ 4] = PFX ## NUM ## _mc01_altivec; \
yading@10 299 c->PFX ## _pixels_tab[IDX][ 5] = PFX ## NUM ## _mc11_altivec; \
yading@10 300 c->PFX ## _pixels_tab[IDX][ 6] = PFX ## NUM ## _mc21_altivec; \
yading@10 301 c->PFX ## _pixels_tab[IDX][ 7] = PFX ## NUM ## _mc31_altivec; \
yading@10 302 c->PFX ## _pixels_tab[IDX][ 8] = PFX ## NUM ## _mc02_altivec; \
yading@10 303 c->PFX ## _pixels_tab[IDX][ 9] = PFX ## NUM ## _mc12_altivec; \
yading@10 304 c->PFX ## _pixels_tab[IDX][10] = PFX ## NUM ## _mc22_altivec; \
yading@10 305 c->PFX ## _pixels_tab[IDX][11] = PFX ## NUM ## _mc32_altivec; \
yading@10 306 c->PFX ## _pixels_tab[IDX][12] = PFX ## NUM ## _mc03_altivec; \
yading@10 307 c->PFX ## _pixels_tab[IDX][13] = PFX ## NUM ## _mc13_altivec; \
yading@10 308 c->PFX ## _pixels_tab[IDX][14] = PFX ## NUM ## _mc23_altivec; \
yading@10 309 c->PFX ## _pixels_tab[IDX][15] = PFX ## NUM ## _mc33_altivec
yading@10 310
yading@10 311 dspfunc(put_h264_qpel, 0, 16);
yading@10 312 dspfunc(avg_h264_qpel, 0, 16);
yading@10 313 #undef dspfunc
yading@10 314 }
yading@10 315 }
yading@10 316 #endif /* HAVE_ALTIVEC */
yading@10 317 }