00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #define ALT_BITSTREAM_READER_LE
00022 #include "avcodec.h"
00023 #include "bitstream.h"
00024 #include "unary.h"
00025
00031 #define WV_JOINT_STEREO 0x00000010
00032 #define WV_FALSE_STEREO 0x40000000
00033
00034 enum WP_ID_Flags{
00035 WP_IDF_MASK = 0x1F,
00036 WP_IDF_IGNORE = 0x20,
00037 WP_IDF_ODD = 0x40,
00038 WP_IDF_LONG = 0x80
00039 };
00040
00041 enum WP_ID{
00042 WP_ID_DUMMY = 0,
00043 WP_ID_ENCINFO,
00044 WP_ID_DECTERMS,
00045 WP_ID_DECWEIGHTS,
00046 WP_ID_DECSAMPLES,
00047 WP_ID_ENTROPY,
00048 WP_ID_HYBRID,
00049 WP_ID_SHAPING,
00050 WP_ID_FLOATINFO,
00051 WP_ID_INT32INFO,
00052 WP_ID_DATA,
00053 WP_ID_CORR,
00054 WP_ID_FLT,
00055 WP_ID_CHANINFO
00056 };
00057
00058 #define MAX_TERMS 16
00059
00060 typedef struct Decorr {
00061 int delta;
00062 int value;
00063 int weightA;
00064 int weightB;
00065 int samplesA[8];
00066 int samplesB[8];
00067 } Decorr;
00068
00069 typedef struct WavpackContext {
00070 AVCodecContext *avctx;
00071 int stereo, stereo_in;
00072 int joint;
00073 uint32_t CRC;
00074 GetBitContext gb;
00075 int data_size;
00076 int samples;
00077 int median[6];
00078 int terms;
00079 Decorr decorr[MAX_TERMS];
00080 int zero, one, zeroes;
00081 int and, or, shift;
00082 } WavpackContext;
00083
00084
00085 static const uint8_t wp_exp2_table [256] = {
00086 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0b,
00087 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x16,
00088 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x21, 0x22, 0x23,
00089 0x24, 0x24, 0x25, 0x26, 0x27, 0x28, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
00090 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3d,
00091 0x3e, 0x3f, 0x40, 0x41, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
00092 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
00093 0x5b, 0x5c, 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
00094 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
00095 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a,
00096 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
00097 0x9c, 0x9d, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad,
00098 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
00099 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf, 0xd0, 0xd2, 0xd3, 0xd4,
00100 0xd6, 0xd7, 0xd8, 0xd9, 0xdb, 0xdc, 0xdd, 0xde, 0xe0, 0xe1, 0xe2, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9,
00101 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff
00102 };
00103
00104 static av_always_inline int wp_exp2(int16_t val)
00105 {
00106 int res, neg = 0;
00107
00108 if(val < 0){
00109 val = -val;
00110 neg = 1;
00111 }
00112
00113 res = wp_exp2_table[val & 0xFF] | 0x100;
00114 val >>= 8;
00115 res = (val > 9) ? (res << (val - 9)) : (res >> (9 - val));
00116 return neg ? -res : res;
00117 }
00118
00119
00120 #define GET_MED(n) ((median[n] >> 4) + 1)
00121 #define DEC_MED(n) median[n] -= ((median[n] + (128>>n) - 2) / (128>>n)) * 2
00122 #define INC_MED(n) median[n] += ((median[n] + (128>>n)) / (128>>n)) * 5
00123
00124
00125 #define UPDATE_WEIGHT_CLIP(weight, delta, samples, in) \
00126 if(samples && in){ \
00127 if((samples ^ in) < 0){ \
00128 weight -= delta; \
00129 if(weight < -1024) weight = -1024; \
00130 }else{ \
00131 weight += delta; \
00132 if(weight > 1024) weight = 1024; \
00133 } \
00134 }
00135
00136
00137 static av_always_inline int get_tail(GetBitContext *gb, int k)
00138 {
00139 int p, e, res;
00140
00141 if(k<1)return 0;
00142 p = av_log2(k);
00143 e = (1 << (p + 1)) - k - 1;
00144 res = p ? get_bits(gb, p) : 0;
00145 if(res >= e){
00146 res = (res<<1) - e + get_bits1(gb);
00147 }
00148 return res;
00149 }
00150
00151 static int wv_get_value(WavpackContext *ctx, GetBitContext *gb, int *median, int *last)
00152 {
00153 int t, t2;
00154 int sign, base, add, ret;
00155
00156 *last = 0;
00157
00158 if((ctx->median[0] < 2U) && (ctx->median[3] < 2U) && !ctx->zero && !ctx->one){
00159 if(ctx->zeroes){
00160 ctx->zeroes--;
00161 if(ctx->zeroes)
00162 return 0;
00163 }else{
00164 t = get_unary_0_33(gb);
00165 if(t >= 2) t = get_bits(gb, t - 1) | (1 << (t-1));
00166 ctx->zeroes = t;
00167 if(ctx->zeroes){
00168 memset(ctx->median, 0, sizeof(ctx->median));
00169 return 0;
00170 }
00171 }
00172 }
00173
00174 if(get_bits_count(gb) >= ctx->data_size){
00175 *last = 1;
00176 return 0;
00177 }
00178
00179 if(ctx->zero){
00180 t = 0;
00181 ctx->zero = 0;
00182 }else{
00183 t = get_unary_0_33(gb);
00184 if(get_bits_count(gb) >= ctx->data_size){
00185 *last = 1;
00186 return 0;
00187 }
00188 if(t == 16) {
00189 t2 = get_unary_0_33(gb);
00190 if(t2 < 2) t += t2;
00191 else t += get_bits(gb, t2 - 1) | (1 << (t2 - 1));
00192 }
00193
00194 if(ctx->one){
00195 ctx->one = t&1;
00196 t = (t>>1) + 1;
00197 }else{
00198 ctx->one = t&1;
00199 t >>= 1;
00200 }
00201 ctx->zero = !ctx->one;
00202 }
00203
00204 if(!t){
00205 base = 0;
00206 add = GET_MED(0) - 1;
00207 DEC_MED(0);
00208 }else if(t == 1){
00209 base = GET_MED(0);
00210 add = GET_MED(1) - 1;
00211 INC_MED(0);
00212 DEC_MED(1);
00213 }else if(t == 2){
00214 base = GET_MED(0) + GET_MED(1);
00215 add = GET_MED(2) - 1;
00216 INC_MED(0);
00217 INC_MED(1);
00218 DEC_MED(2);
00219 }else{
00220 base = GET_MED(0) + GET_MED(1) + GET_MED(2) * (t - 2);
00221 add = GET_MED(2) - 1;
00222 INC_MED(0);
00223 INC_MED(1);
00224 INC_MED(2);
00225 }
00226 ret = base + get_tail(gb, add);
00227 sign = get_bits1(gb);
00228 return sign ? ~ret : ret;
00229 }
00230
00231 static int wv_unpack_stereo(WavpackContext *s, GetBitContext *gb, int16_t *dst)
00232 {
00233 int i, j, count = 0;
00234 int last, t;
00235 int A, B, L, L2, R, R2, bit;
00236 int pos = 0;
00237 uint32_t crc = 0xFFFFFFFF;
00238
00239 s->one = s->zero = s->zeroes = 0;
00240 do{
00241 L = wv_get_value(s, gb, s->median, &last);
00242 if(last) break;
00243 R = wv_get_value(s, gb, s->median + 3, &last);
00244 if(last) break;
00245 for(i = 0; i < s->terms; i++){
00246 t = s->decorr[i].value;
00247 j = 0;
00248 if(t > 0){
00249 if(t > 8){
00250 if(t & 1){
00251 A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1];
00252 B = 2 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1];
00253 }else{
00254 A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1;
00255 B = (3 * s->decorr[i].samplesB[0] - s->decorr[i].samplesB[1]) >> 1;
00256 }
00257 s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0];
00258 s->decorr[i].samplesB[1] = s->decorr[i].samplesB[0];
00259 j = 0;
00260 }else{
00261 A = s->decorr[i].samplesA[pos];
00262 B = s->decorr[i].samplesB[pos];
00263 j = (pos + t) & 7;
00264 }
00265 L2 = L + ((s->decorr[i].weightA * A + 512) >> 10);
00266 R2 = R + ((s->decorr[i].weightB * B + 512) >> 10);
00267 if(A && L) s->decorr[i].weightA -= ((((L ^ A) >> 30) & 2) - 1) * s->decorr[i].delta;
00268 if(B && R) s->decorr[i].weightB -= ((((R ^ B) >> 30) & 2) - 1) * s->decorr[i].delta;
00269 s->decorr[i].samplesA[j] = L = L2;
00270 s->decorr[i].samplesB[j] = R = R2;
00271 }else if(t == -1){
00272 L2 = L + ((s->decorr[i].weightA * s->decorr[i].samplesA[0] + 512) >> 10);
00273 UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, s->decorr[i].samplesA[0], L);
00274 L = L2;
00275 R2 = R + ((s->decorr[i].weightB * L2 + 512) >> 10);
00276 UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, L2, R);
00277 R = R2;
00278 s->decorr[i].samplesA[0] = R;
00279 }else{
00280 R2 = R + ((s->decorr[i].weightB * s->decorr[i].samplesB[0] + 512) >> 10);
00281 UPDATE_WEIGHT_CLIP(s->decorr[i].weightB, s->decorr[i].delta, s->decorr[i].samplesB[0], R);
00282 R = R2;
00283
00284 if(t == -3){
00285 R2 = s->decorr[i].samplesA[0];
00286 s->decorr[i].samplesA[0] = R;
00287 }
00288
00289 L2 = L + ((s->decorr[i].weightA * R2 + 512) >> 10);
00290 UPDATE_WEIGHT_CLIP(s->decorr[i].weightA, s->decorr[i].delta, R2, L);
00291 L = L2;
00292 s->decorr[i].samplesB[0] = L;
00293 }
00294 }
00295 pos = (pos + 1) & 7;
00296 if(s->joint)
00297 L += (R -= (L >> 1));
00298 crc = (crc * 3 + L) * 3 + R;
00299 bit = (L & s->and) | s->or;
00300 *dst++ = ((L + bit) << s->shift) - bit;
00301 bit = (R & s->and) | s->or;
00302 *dst++ = ((R + bit) << s->shift) - bit;
00303 count++;
00304 }while(!last && count < s->samples);
00305
00306 if(crc != s->CRC){
00307 av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
00308 return -1;
00309 }
00310 return count * 2;
00311 }
00312
00313 static int wv_unpack_mono(WavpackContext *s, GetBitContext *gb, int16_t *dst)
00314 {
00315 int i, j, count = 0;
00316 int last, t;
00317 int A, S, T, bit;
00318 int pos = 0;
00319 uint32_t crc = 0xFFFFFFFF;
00320
00321 s->one = s->zero = s->zeroes = 0;
00322 do{
00323 T = wv_get_value(s, gb, s->median, &last);
00324 S = 0;
00325 if(last) break;
00326 for(i = 0; i < s->terms; i++){
00327 t = s->decorr[i].value;
00328 if(t > 8){
00329 if(t & 1)
00330 A = 2 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1];
00331 else
00332 A = (3 * s->decorr[i].samplesA[0] - s->decorr[i].samplesA[1]) >> 1;
00333 s->decorr[i].samplesA[1] = s->decorr[i].samplesA[0];
00334 j = 0;
00335 }else{
00336 A = s->decorr[i].samplesA[pos];
00337 j = (pos + t) & 7;
00338 }
00339 S = T + ((s->decorr[i].weightA * A + 512) >> 10);
00340 if(A && T) s->decorr[i].weightA -= ((((T ^ A) >> 30) & 2) - 1) * s->decorr[i].delta;
00341 s->decorr[i].samplesA[j] = T = S;
00342 }
00343 pos = (pos + 1) & 7;
00344 crc = crc * 3 + S;
00345 bit = (S & s->and) | s->or;
00346 *dst++ = ((S + bit) << s->shift) - bit;
00347 count++;
00348 }while(!last && count < s->samples);
00349
00350 if(crc != s->CRC){
00351 av_log(s->avctx, AV_LOG_ERROR, "CRC error\n");
00352 return -1;
00353 }
00354 return count;
00355 }
00356
00357 static int wavpack_decode_init(AVCodecContext *avctx)
00358 {
00359 WavpackContext *s = avctx->priv_data;
00360
00361 s->avctx = avctx;
00362 s->stereo = (avctx->channels == 2);
00363
00364 return 0;
00365 }
00366
00367 static int wavpack_decode_frame(AVCodecContext *avctx,
00368 void *data, int *data_size,
00369 const uint8_t *buf, int buf_size)
00370 {
00371 WavpackContext *s = avctx->priv_data;
00372 int16_t *samples = data;
00373 int samplecount;
00374 int got_terms = 0, got_weights = 0, got_samples = 0, got_entropy = 0, got_bs = 0;
00375 const uint8_t* buf_end = buf + buf_size;
00376 int i, j, id, size, ssize, weights, t;
00377
00378 if (buf_size == 0){
00379 *data_size = 0;
00380 return 0;
00381 }
00382
00383 memset(s->decorr, 0, MAX_TERMS * sizeof(Decorr));
00384 memset(s->median, 0, sizeof(s->median));
00385 s->and = s->or = s->shift = 0;
00386
00387 s->samples = AV_RL32(buf); buf += 4;
00388 if(!s->samples){
00389 *data_size = 0;
00390 return buf_size;
00391 }
00392
00393 if(s->samples * 2 * avctx->channels > *data_size){
00394 av_log(avctx, AV_LOG_ERROR, "Packet size is too big to be handled in lavc!\n");
00395 return -1;
00396 }
00397 s->stereo_in = (AV_RL32(buf) & WV_FALSE_STEREO) ? 0 : s->stereo;
00398 s->joint = AV_RL32(buf) & WV_JOINT_STEREO; buf += 4;
00399 s->CRC = AV_RL32(buf); buf += 4;
00400
00401 while(buf < buf_end){
00402 id = *buf++;
00403 size = *buf++;
00404 if(id & WP_IDF_LONG) {
00405 size |= (*buf++) << 8;
00406 size |= (*buf++) << 16;
00407 }
00408 size <<= 1;
00409 ssize = size;
00410 if(id & WP_IDF_ODD) size--;
00411 if(size < 0){
00412 av_log(avctx, AV_LOG_ERROR, "Got incorrect block %02X with size %i\n", id, size);
00413 break;
00414 }
00415 if(buf + ssize > buf_end){
00416 av_log(avctx, AV_LOG_ERROR, "Block size %i is out of bounds\n", size);
00417 break;
00418 }
00419 if(id & WP_IDF_IGNORE){
00420 buf += ssize;
00421 continue;
00422 }
00423 switch(id & WP_IDF_MASK){
00424 case WP_ID_DECTERMS:
00425 s->terms = size;
00426 if(s->terms > MAX_TERMS){
00427 av_log(avctx, AV_LOG_ERROR, "Too many decorrelation terms\n");
00428 buf += ssize;
00429 continue;
00430 }
00431 for(i = 0; i < s->terms; i++) {
00432 s->decorr[s->terms - i - 1].value = (*buf & 0x1F) - 5;
00433 s->decorr[s->terms - i - 1].delta = *buf >> 5;
00434 buf++;
00435 }
00436 got_terms = 1;
00437 break;
00438 case WP_ID_DECWEIGHTS:
00439 if(!got_terms){
00440 av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n");
00441 continue;
00442 }
00443 weights = size >> s->stereo_in;
00444 if(weights > MAX_TERMS || weights > s->terms){
00445 av_log(avctx, AV_LOG_ERROR, "Too many decorrelation weights\n");
00446 buf += ssize;
00447 continue;
00448 }
00449 for(i = 0; i < weights; i++) {
00450 t = (int8_t)(*buf++);
00451 s->decorr[s->terms - i - 1].weightA = t << 3;
00452 if(s->decorr[s->terms - i - 1].weightA > 0)
00453 s->decorr[s->terms - i - 1].weightA += (s->decorr[s->terms - i - 1].weightA + 64) >> 7;
00454 if(s->stereo_in){
00455 t = (int8_t)(*buf++);
00456 s->decorr[s->terms - i - 1].weightB = t << 3;
00457 if(s->decorr[s->terms - i - 1].weightB > 0)
00458 s->decorr[s->terms - i - 1].weightB += (s->decorr[s->terms - i - 1].weightB + 64) >> 7;
00459 }
00460 }
00461 got_weights = 1;
00462 break;
00463 case WP_ID_DECSAMPLES:
00464 if(!got_terms){
00465 av_log(avctx, AV_LOG_ERROR, "No decorrelation terms met\n");
00466 continue;
00467 }
00468 t = 0;
00469 for(i = s->terms - 1; (i >= 0) && (t < size); i--) {
00470 if(s->decorr[i].value > 8){
00471 s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2;
00472 s->decorr[i].samplesA[1] = wp_exp2(AV_RL16(buf)); buf += 2;
00473 if(s->stereo_in){
00474 s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2;
00475 s->decorr[i].samplesB[1] = wp_exp2(AV_RL16(buf)); buf += 2;
00476 t += 4;
00477 }
00478 t += 4;
00479 }else if(s->decorr[i].value < 0){
00480 s->decorr[i].samplesA[0] = wp_exp2(AV_RL16(buf)); buf += 2;
00481 s->decorr[i].samplesB[0] = wp_exp2(AV_RL16(buf)); buf += 2;
00482 t += 4;
00483 }else{
00484 for(j = 0; j < s->decorr[i].value; j++){
00485 s->decorr[i].samplesA[j] = wp_exp2(AV_RL16(buf)); buf += 2;
00486 if(s->stereo_in){
00487 s->decorr[i].samplesB[j] = wp_exp2(AV_RL16(buf)); buf += 2;
00488 }
00489 }
00490 t += s->decorr[i].value * 2 * (s->stereo_in + 1);
00491 }
00492 }
00493 got_samples = 1;
00494 break;
00495 case WP_ID_ENTROPY:
00496 if(size != 6 * (s->stereo_in + 1)){
00497 av_log(avctx, AV_LOG_ERROR, "Entropy vars size should be %i, got %i", 6 * (s->stereo_in + 1), size);
00498 buf += ssize;
00499 continue;
00500 }
00501 for(i = 0; i < 3 * (s->stereo_in + 1); i++){
00502 s->median[i] = wp_exp2(AV_RL16(buf));
00503 buf += 2;
00504 }
00505 got_entropy = 1;
00506 break;
00507 case WP_ID_INT32INFO:
00508 if(size != 4 || *buf){
00509 av_log(avctx, AV_LOG_ERROR, "Invalid INT32INFO, size = %i, sent_bits = %i\n", size, *buf);
00510 buf += ssize;
00511 continue;
00512 }
00513 if(buf[1])
00514 s->shift = buf[1];
00515 else if(buf[2]){
00516 s->and = s->or = 1;
00517 s->shift = buf[2];
00518 }else if(buf[3]){
00519 s->and = 1;
00520 s->shift = buf[3];
00521 }
00522 buf += 4;
00523 break;
00524 case WP_ID_DATA:
00525 init_get_bits(&s->gb, buf, size * 8);
00526 s->data_size = size * 8;
00527 buf += size;
00528 got_bs = 1;
00529 break;
00530 default:
00531 buf += size;
00532 }
00533 if(id & WP_IDF_ODD) buf++;
00534 }
00535 if(!got_terms){
00536 av_log(avctx, AV_LOG_ERROR, "No block with decorrelation terms\n");
00537 return -1;
00538 }
00539 if(!got_weights){
00540 av_log(avctx, AV_LOG_ERROR, "No block with decorrelation weights\n");
00541 return -1;
00542 }
00543 if(!got_samples){
00544 av_log(avctx, AV_LOG_ERROR, "No block with decorrelation samples\n");
00545 return -1;
00546 }
00547 if(!got_entropy){
00548 av_log(avctx, AV_LOG_ERROR, "No block with entropy info\n");
00549 return -1;
00550 }
00551 if(!got_bs){
00552 av_log(avctx, AV_LOG_ERROR, "Packed samples not found\n");
00553 return -1;
00554 }
00555
00556 if(s->stereo_in)
00557 samplecount = wv_unpack_stereo(s, &s->gb, samples);
00558 else{
00559 samplecount = wv_unpack_mono(s, &s->gb, samples);
00560 if(s->stereo){
00561 int16_t *dst = samples + samplecount * 2;
00562 int16_t *src = samples + samplecount;
00563 int cnt = samplecount;
00564 while(cnt--){
00565 *--dst = *--src;
00566 *--dst = *src;
00567 }
00568 samplecount *= 2;
00569 }
00570 }
00571 *data_size = samplecount * 2;
00572
00573 return buf_size;
00574 }
00575
00576 AVCodec wavpack_decoder = {
00577 "wavpack",
00578 CODEC_TYPE_AUDIO,
00579 CODEC_ID_WAVPACK,
00580 sizeof(WavpackContext),
00581 wavpack_decode_init,
00582 NULL,
00583 NULL,
00584 wavpack_decode_frame,
00585 };