static void path_sendraw(struct net_seq_stream *net, char *url, char *hdr, char *data, int dlen) { int i; struct nrf_raw_msg msg; chprintf((BaseSequentialStream *)net, "HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\n"); if (dlen != PAYLOADSZ * 2) goto out; for (i = 0; i < PAYLOADSZ; i++) { if (!nibble_valid(data[i * 2]) || !nibble_valid(data[i * 2 + 1])) goto out; msg.data[i] = (get_nibble(data[i * 2]) << 4) | get_nibble(data[i * 2 + 1]); } nrf_send(&msg); chprintf((BaseSequentialStream *)net, "OK\r\n"); return; out: chprintf((BaseSequentialStream *)net, "ERR\r\n"); }
static uint16 get_nibbles(uint8 *mem,uint16 *nbnum,uint8 nbs) { uint16 res = 0; while (nbs--) { res <<= 4; res |= get_nibble(mem,nbnum); } return res; }
static int unpack_block(struct module_data *m, uint16 bnum, uint8 *from) { struct xmp_module *mod = &m->mod; struct xmp_event *event; uint32 linemsk0 = *((uint32 *)from), linemsk1 = *((uint32 *)from + 1); uint32 fxmsk0 = *((uint32 *)from + 2), fxmsk1 = *((uint32 *)from + 3); uint32 *lmptr = &linemsk0, *fxptr = &fxmsk0; uint16 fromn = 0, lmsk; uint8 *fromst = from + 16, bcnt, *tmpto; uint8 *patbuf, *to; int i, j, trkn = mod->chn; from += 16; patbuf = to = calloc(3, 4 * 64); if (to == NULL) return -1; for (i = 0; i < 64; i++) { if (i == 32) { lmptr = &linemsk1; fxptr = &fxmsk1; } if (*lmptr & MASK) { lmsk = get_nibbles(fromst, &fromn, (uint8)(trkn / 4)); lmsk <<= (16 - trkn); tmpto = to; for (bcnt = 0; bcnt < trkn; bcnt++) { if (lmsk & 0x8000) { *tmpto = (uint8)get_nibbles(fromst, &fromn,2); *(tmpto + 1) = (get_nibble(fromst, &fromn) << 4); } lmsk <<= 1; tmpto += 3; } } if (*fxptr & MASK) { lmsk = get_nibbles(fromst,&fromn,(uint8)(trkn / 4)); lmsk <<= (16 - trkn); tmpto = to; for (bcnt = 0; bcnt < trkn; bcnt++) { if (lmsk & 0x8000) { *(tmpto+1) |= get_nibble(fromst, &fromn); *(tmpto+2) = (uint8)get_nibbles(fromst, &fromn,2); } lmsk <<= 1; tmpto += 3; } } to += 3 * trkn; *lmptr <<= 1; *fxptr <<= 1; } for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { event = &EVENT(bnum, j, i); event->note = patbuf[i * 12 + j * 3 + 0]; if (event->note) event->note += 48; event->ins = patbuf[i * 12 + j * 3 + 1] >> 4; if (event->ins) event->ins++; event->fxt = patbuf[i * 12 + j * 3 + 1] & 0x0f; event->fxp = patbuf[i * 12 + j * 3 + 2]; switch (event->fxt) { case 0x00: /* arpeggio */ case 0x01: /* slide up */ case 0x02: /* slide down */ case 0x03: /* portamento */ case 0x04: /* vibrato? */ break; case 0x0c: /* set volume (BCD) */ event->fxp = MSN(event->fxp) * 10 + LSN(event->fxp); break; case 0x0d: /* volume slides */ event->fxt = FX_VOLSLIDE; break; case 0x0f: /* tempo/break */ if (event->fxp == 0) event->fxt = FX_BREAK; if (event->fxp == 0xff) { event->fxp = event->fxt = 0; event->vol = 1; } else if (event->fxp == 0xfe) { event->fxp = event->fxt = 0; } else if (event->fxp == 0xf1) { event->fxt = FX_EXTENDED; event->fxp = (EX_RETRIG << 4) | 3; } else if (event->fxp == 0xf2) { event->fxt = FX_EXTENDED; event->fxp = (EX_CUT << 4) | 3; } else if (event->fxp == 0xf3) { event->fxt = FX_EXTENDED; event->fxp = (EX_DELAY << 4) | 3; } else if (event->fxp > 10) { event->fxt = FX_S3M_BPM; event->fxp = 125 * event->fxp / 33; } break; default: event->fxp = event->fxt = 0; } } } free(patbuf); return 0; }
/* This is largely from spudec, ffmpeg */ int decompress_subtitle(mpeg3_t *file, mpeg3_subtitle_t *subtitle) { int i, j, pass; unsigned char *ptr = subtitle->data; unsigned char *end = subtitle->data + subtitle->size; int even_offset = 0; int odd_offset = 0; /* packet size */ ptr += 2; /* data packet size */ if(ptr + 2 > end) return 1; int data_size = (*ptr++) << 8; data_size |= *ptr++; unsigned char *data_start = ptr; /* * printf("decompress_subtitle %d 0x%02x%02x size=%d data_size=%d\n", * __LINE__, * subtitle->data[0], * subtitle->data[1], * subtitle->size, * data_size); */ // if(ptr + data_size - 2 > end) return 1; /* Advance to control sequences */ ptr += data_size - 2; subtitle->palette[0] = 0x00; subtitle->palette[1] = 0x01; subtitle->palette[2] = 0x02; subtitle->palette[3] = 0x03; subtitle->alpha[0] = 0xff; subtitle->alpha[1] = 0xff; subtitle->alpha[2] = 0xff; subtitle->alpha[3] = 0xff; subtitle->x1 = 0; subtitle->x2 = 720; subtitle->y1 = 2; subtitle->y2 = 575; subtitle->w = 720; subtitle->h = 575; subtitle->start_time = 1897; subtitle->stop_time = 175; /* Control sequence */ unsigned char *control_start = 0; unsigned char *next_control_start = ptr; int got_alpha = 0; while(ptr < end && control_start != next_control_start) { control_start = next_control_start; /* Date */ if(ptr + 2 > end) break; int date = (*ptr++) << 8; date |= *ptr++; /* Offset of next control sequence */ if(ptr + 2 > end) break; int next = (*ptr++) << 8; next |= *ptr++; next_control_start = subtitle->data + next; int done = 0; while(ptr < end && !done) { int type = *ptr++; switch(type) { case 0x00: subtitle->force = 1; break; case 0x01: subtitle->start_time = date; //printf("decompress_subtitle %d\n", subtitle->start_time); break; case 0x02: subtitle->stop_time = date; break; case 0x03: /* Entry in palette of each color */ if(ptr + 2 > end) return 1; //printf("decompress_subtitle %d\n", __LINE__); subtitle->palette[0] = (*ptr) >> 4; subtitle->palette[1] = (*ptr++) & 0xf; subtitle->palette[2] = (*ptr) >> 4; subtitle->palette[3] = (*ptr++) & 0xf; //printf("subtitle palette %d %d %d %d\n", subtitle->palette[0], subtitle->palette[1], subtitle->palette[2], subtitle->palette[3]); break; case 0x04: /* Alpha corresponding to each color */ if(ptr + 2 > end) return 1; //printf("decompress_subtitle %d\n", __LINE__); subtitle->alpha[3] = ((*ptr) >> 4) * 255 / 15; subtitle->alpha[2] = ((*ptr++) & 0xf) * 255 / 15; subtitle->alpha[1] = ((*ptr) >> 4) * 255 / 15; subtitle->alpha[0] = ((*ptr++) & 0xf) * 255 / 15; got_alpha = 1; //printf("subtitle alphas %d %d %d %d\n", subtitle->alpha[0], subtitle->alpha[1], subtitle->alpha[2], subtitle->alpha[3]); #ifdef OVERRIDE_ALPHA subtitle->alpha[3] = 0xff; subtitle->alpha[2] = 0x80; subtitle->alpha[1] = 0x40; subtitle->alpha[0] = 0x00; #endif break; case 0x05: /* Extent of image on screen */ if(ptr + 6 > end) return 1; //printf("decompress_subtitle %d\n", __LINE__); /* * printf("decompress_subtitle 10 %02x %02x %02x %02x %02x %02x\n", * ptr[0], * ptr[1], * ptr[2], * ptr[3], * ptr[4], * ptr[5]); */ subtitle->x1 = (*ptr++) << 4; subtitle->x1 |= (*ptr) >> 4; subtitle->x2 = ((*ptr++) & 0xf) << 8; subtitle->x2 |= *ptr++; subtitle->y1 = (*ptr++) << 4; subtitle->y1 |= (*ptr) >> 4; subtitle->y2 = ((*ptr++) & 0xf) << 8; subtitle->y2 |= *ptr++; subtitle->x2++; subtitle->y2++; subtitle->w = subtitle->x2 - subtitle->x1; subtitle->h = subtitle->y2 - subtitle->y1 + 2; /* * printf("decompress_subtitle 20 x1=%d x2=%d y1=%d y2=%d\n", * subtitle->x1, * subtitle->x2, * subtitle->y1, * subtitle->y2); */ CLAMP(subtitle->w, 1, 2048); CLAMP(subtitle->h, 1, 2048); CLAMP(subtitle->x1, 0, 2048); CLAMP(subtitle->x2, 0, 2048); CLAMP(subtitle->y1, 0, 2048); CLAMP(subtitle->y2, 0, 2048); break; case 0x06: /* offsets of even and odd field in compressed data */ if(ptr + 4 > end) return 1; //printf("decompress_subtitle %d\n", __LINE__); even_offset = (ptr[0] << 8) | (ptr[1]); odd_offset = (ptr[2] << 8) | (ptr[3]); //printf("decompress_subtitle 30 even=0x%x odd=0x%x\n", even_offset, odd_offset); ptr += 4; break; case 0xff: done = 1; break; default: // printf("unknown type %02x\n", type); break; } } } /* Allocate image buffer */ subtitle->image_y = (unsigned char*)calloc(1, subtitle->w * subtitle->h + subtitle->w); subtitle->image_u = (unsigned char*)calloc(1, subtitle->w * subtitle->h + subtitle->w); subtitle->image_v = (unsigned char*)calloc(1, subtitle->w * subtitle->h + subtitle->w); subtitle->image_a = (unsigned char*)calloc(1, subtitle->w * subtitle->h + subtitle->w); /* Decode image */ int current_nibble = 0; int x = 0, y = 0, field = 0; ptr = data_start; int first_pixel = 1; while(ptr < end && y < subtitle->h + 1 && x < subtitle->w) { // Start new field based on offset, not total lines if(ptr - data_start >= odd_offset - 4 && field == 0) { // Only decode even field because too many bugs #ifdef USE_INTERLACE field = 1; #ifndef SWAP_FIELDS y = FIELD_OFFSET1; #endif x = 0; if(current_nibble) { ptr++; current_nibble = 0; } #else break; #endif } unsigned int code = get_nibble(&ptr, ¤t_nibble); if(code < 0x4 && ptr < end) { code = (code << 4) | get_nibble(&ptr, ¤t_nibble); if(code < 0x10 && ptr < end) { code = (code << 4) | get_nibble(&ptr, ¤t_nibble); if(code < 0x40 && ptr < end) { code = (code << 4) | get_nibble(&ptr, ¤t_nibble); /* carriage return */ if(code < 0x4 && ptr < end) code |= (subtitle->w - x) << 2; } } } int color = (code & 0x3); int len = code >> 2; //if(len == 0 || len >= subtitle->w - x) printf("%d\n", len); if(len > subtitle->w - x) len = subtitle->w - x; int y_color = file->palette[subtitle->palette[color] * 4 + 0]; int u_color = file->palette[subtitle->palette[color] * 4 + 1]; int v_color = file->palette[subtitle->palette[color] * 4 + 2]; int a_color = subtitle->alpha[color]; // The alpha seems to be arbitrary. Assume the top left pixel is always // transparent. if(first_pixel) { subtitle->alpha[color] = 0x0; a_color = 0x0; first_pixel = 0; } /* * printf("0x%02x 0x%02x 0x%02x\n", * y_color, * u_color, * v_color); */ if(y < subtitle->h - 1) { for(i = 0; i < len; i++) { subtitle->image_y[y * subtitle->w + x] = y_color; subtitle->image_u[y * subtitle->w + x] = u_color; subtitle->image_v[y * subtitle->w + x] = v_color; subtitle->image_a[y * subtitle->w + x] = a_color; #ifndef USE_INTERLACE subtitle->image_y[(y + 1) * subtitle->w + x] = y_color; subtitle->image_u[(y + 1) * subtitle->w + x] = u_color; subtitle->image_v[(y + 1) * subtitle->w + x] = v_color; subtitle->image_a[(y + 1) * subtitle->w + x] = a_color; #endif x++; } } if(x >= subtitle->w) { x = 0; y += 2; /* Byte alignment */ if(current_nibble) { ptr++; current_nibble = 0; } // Clamp y if(y >= subtitle->h) { #ifdef SWAP_FIELDS y++; #endif while(y >= subtitle->h) y -= subtitle->h; } } } #if 1 // Normalize image colors float min_h = 360; float max_h = 0; float threshold; #define HISTOGRAM_SIZE 1000 // Decompression coefficients straight out of jpeglib #define V_TO_R 1.40200 #define V_TO_G -0.71414 #define U_TO_G -0.34414 #define U_TO_B 1.77200 unsigned char histogram[HISTOGRAM_SIZE]; bzero(histogram, HISTOGRAM_SIZE); for(pass = 0; pass < 2; pass++) { for(i = 0; i < subtitle->h; i++) { for(j = 0; j < subtitle->w; j++) { if(subtitle->image_a[i * subtitle->w + j]) { unsigned char *y_color = subtitle->image_y + i * subtitle->w + j; unsigned char *u_color = subtitle->image_u + i * subtitle->w + j; unsigned char *v_color = subtitle->image_v + i * subtitle->w + j; unsigned char *a_color = subtitle->image_a + i * subtitle->w + j; // Convert to RGB float r = (*y_color + *v_color * V_TO_R); float g = (*y_color + *u_color * U_TO_G + *v_color * V_TO_G); float b = (*y_color + *u_color * U_TO_B); // Multiply alpha /* * r = r * *a_color / 0xff; * g = g * *a_color / 0xff; * b = b * *a_color / 0xff; */ // Convert to HSV float h, s, v; float min, max, delta; float f, p, q, t; min = ((r < g) ? r : g) < b ? ((r < g) ? r : g) : b; max = ((r > g) ? r : g) > b ? ((r > g) ? r : g) : b; v = max; delta = max - min; if(max != 0 && delta != 0) { s = delta / max; // s if(r == max) h = (g - b) / delta; // between yellow & magenta else if(g == max) h = 2 + (b - r) / delta; // between cyan & yellow else h = 4 + (r - g) / delta; // between magenta & cyan h *= 60; // degrees if(h < 0) h += 360; } else { // r = g = b = 0 // s = 0, v is undefined s = 0; h = -1; } /* * int magnitude = (int)(*y_color * *y_color + * *u_color * *u_color + * *v_color * *v_color); */ // Multiply alpha h = h * *a_color / 0xff; if(pass == 0) { histogram[(int)h]++; if(h < min_h) min_h = h; if(h > max_h) max_h = h; } else { // Set new color in a 2x2 pixel block #ifdef MONOCHROME if(h > threshold) { *y_color = 0xff; } else { *y_color = 0; } *u_color = 0x80; *v_color = 0x80; #endif *a_color = 0xff; } } } } if(pass == 0) { /* * int hist_total = 0; * for(i = 0; i < HISTOGRAM_SIZE; i++) * { * hist_total += histogram[i]; * } * * int hist_count = 0; * for(i = 0; i < HISTOGRAM_SIZE; i++) * { * hist_count += histogram[i]; * if(hist_count > hist_total * 1 / 3) * { * threshold = i; * break; * } * } */ threshold = (min_h + max_h) / 2; // threshold = 324; //printf("min_h=%f max_h=%f threshold=%f\n", min_h, max_h, threshold); } } #endif // 0 /* * printf("decompress_subtitle coords: %d,%d - %d,%d size: %d,%d start_time=%d end_time=%d\n", * subtitle->x1, * subtitle->y1, * subtitle->x2, * subtitle->y2, * subtitle->w, * subtitle->h, * subtitle->start_time, * subtitle->stop_time); */ return 0; }