📄 vobsub.c
字号:
if (pkt->data) free(pkt->data);}static voidpacket_queue_construct(packet_queue_t *queue){ queue->id = NULL; queue->packets = NULL; queue->packets_reserve = 0; queue->packets_size = 0; queue->current_index = 0;}static voidpacket_queue_destroy(packet_queue_t *queue){ if (queue->packets) { while (queue->packets_size--) packet_destroy(queue->packets + queue->packets_size); free(queue->packets); } return;}/* Make sure there is enough room for needed_size packets in the packet queue. */static intpacket_queue_ensure(packet_queue_t *queue, unsigned int needed_size){ if (queue->packets_reserve < needed_size) { if (queue->packets) { packet_t *tmp = realloc(queue->packets, 2 * queue->packets_reserve * sizeof(packet_t)); if (tmp == NULL) { mp_msg(MSGT_VOBSUB,MSGL_FATAL,"realloc failure"); return -1; } queue->packets = tmp; queue->packets_reserve *= 2; } else { queue->packets = malloc(sizeof(packet_t)); if (queue->packets == NULL) { mp_msg(MSGT_VOBSUB,MSGL_FATAL,"malloc failure"); return -1; } queue->packets_reserve = 1; } } return 0;}/* add one more packet */static intpacket_queue_grow(packet_queue_t *queue){ if (packet_queue_ensure(queue, queue->packets_size + 1) < 0) return -1; packet_construct(queue->packets + queue->packets_size); ++queue->packets_size; return 0;}/* insert a new packet, duplicating pts from the current one */static intpacket_queue_insert(packet_queue_t *queue){ packet_t *pkts; if (packet_queue_ensure(queue, queue->packets_size + 1) < 0) return -1; /* XXX packet_size does not reflect the real thing here, it will be updated a bit later */ memmove(queue->packets + queue->current_index + 2, queue->packets + queue->current_index + 1, sizeof(packet_t) * (queue->packets_size - queue->current_index - 1)); pkts = queue->packets + queue->current_index; ++queue->packets_size; ++queue->current_index; packet_construct(pkts + 1); pkts[1].pts100 = pkts[0].pts100; pkts[1].filepos = pkts[0].filepos; return 0;}/********************************************************************** * Vobsub **********************************************************************/typedef struct { unsigned int palette[16]; unsigned int cuspal[4]; int delay; unsigned int custom; unsigned int have_palette; unsigned int orig_frame_width, orig_frame_height; unsigned int origin_x, origin_y; unsigned int forced_subs; /* index */ packet_queue_t *spu_streams; unsigned int spu_streams_size; unsigned int spu_streams_current;} vobsub_t;/* Make sure that the spu stream idx exists. */static intvobsub_ensure_spu_stream(vobsub_t *vob, unsigned int index){ if (index >= vob->spu_streams_size) { /* This is a new stream */ if (vob->spu_streams) { packet_queue_t *tmp = realloc(vob->spu_streams, (index + 1) * sizeof(packet_queue_t)); if (tmp == NULL) { mp_msg(MSGT_VOBSUB,MSGL_ERR,"vobsub_ensure_spu_stream: realloc failure"); return -1; } vob->spu_streams = tmp; } else { vob->spu_streams = malloc((index + 1) * sizeof(packet_queue_t)); if (vob->spu_streams == NULL) { mp_msg(MSGT_VOBSUB,MSGL_ERR,"vobsub_ensure_spu_stream: malloc failure"); return -1; } } while (vob->spu_streams_size <= index) { packet_queue_construct(vob->spu_streams + vob->spu_streams_size); ++vob->spu_streams_size; } } return 0;}static intvobsub_add_id(vobsub_t *vob, const char *id, size_t idlen, const unsigned int index){ if (vobsub_ensure_spu_stream(vob, index) < 0) return -1; if (id && idlen) { if (vob->spu_streams[index].id) free(vob->spu_streams[index].id); vob->spu_streams[index].id = malloc(idlen + 1); if (vob->spu_streams[index].id == NULL) { mp_msg(MSGT_VOBSUB,MSGL_FATAL,"vobsub_add_id: malloc failure"); return -1; } vob->spu_streams[index].id[idlen] = 0; memcpy(vob->spu_streams[index].id, id, idlen); } vob->spu_streams_current = index; if (identify) { mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VOBSUB_ID=%d\n", index); if (id && idlen) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VSID_%d_LANG=%s\n", index, vob->spu_streams[index].id); } mp_msg(MSGT_VOBSUB,MSGL_V,"[vobsub] subtitle (vobsubid): %d language %s\n", index, vob->spu_streams[index].id); return 0;}static intvobsub_add_timestamp(vobsub_t *vob, off_t filepos, int ms){ packet_queue_t *queue; packet_t *pkt; if (vob->spu_streams == 0) { mp_msg(MSGT_VOBSUB,MSGL_WARN,"[vobsub] warning, binning some index entries. Check your index file\n"); return -1; } queue = vob->spu_streams + vob->spu_streams_current; if (packet_queue_grow(queue) >= 0) { pkt = queue->packets + (queue->packets_size - 1); pkt->filepos = filepos; pkt->pts100 = ms < 0 ? UINT_MAX : (unsigned int)ms * 90; return 0; } return -1;}static intvobsub_parse_id(vobsub_t *vob, const char *line){ // id: xx, index: n size_t idlen; const char *p, *q; p = line; while (isspace(*p)) ++p; q = p; while (isalpha(*q)) ++q; idlen = q - p; if (idlen == 0) return -1; ++q; while (isspace(*q)) ++q; if (strncmp("index:", q, 6)) return -1; q += 6; while (isspace(*q)) ++q; if (!isdigit(*q)) return -1; return vobsub_add_id(vob, p, idlen, atoi(q));}static intvobsub_parse_timestamp(vobsub_t *vob, const char *line){ // timestamp: HH:MM:SS.mmm, filepos: 0nnnnnnnnn const char *p; int h, m, s, ms; off_t filepos; while (isspace(*line)) ++line; p = line; while (isdigit(*p)) ++p; if (p - line != 2) return -1; h = atoi(line); if (*p != ':') return -1; line = ++p; while (isdigit(*p)) ++p; if (p - line != 2) return -1; m = atoi(line); if (*p != ':') return -1; line = ++p; while (isdigit(*p)) ++p; if (p - line != 2) return -1; s = atoi(line); if (*p != ':') return -1; line = ++p; while (isdigit(*p)) ++p; if (p - line != 3) return -1; ms = atoi(line); if (*p != ',') return -1; line = p + 1; while (isspace(*line)) ++line; if (strncmp("filepos:", line, 8)) return -1; line += 8; while (isspace(*line)) ++line; if (! isxdigit(*line)) return -1; filepos = strtol(line, NULL, 16); return vobsub_add_timestamp(vob, filepos, vob->delay + ms + 1000 * (s + 60 * (m + 60 * h)));}static intvobsub_parse_size(vobsub_t *vob, const char *line){ // size: WWWxHHH char *p; while (isspace(*line)) ++line; if (!isdigit(*line)) return -1; vob->orig_frame_width = strtoul(line, &p, 10); if (*p != 'x') return -1; ++p; vob->orig_frame_height = strtoul(p, NULL, 10); return 0;}static intvobsub_parse_origin(vobsub_t *vob, const char *line){ // org: X,Y char *p; while (isspace(*line)) ++line; if (!isdigit(*line)) return -1; vob->origin_x = strtoul(line, &p, 10); if (*p != ',') return -1; ++p; vob->origin_y = strtoul(p, NULL, 10); return 0;}static intvobsub_parse_palette(vobsub_t *vob, const char *line){ // palette: XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX unsigned int n; n = 0; while (1) { const char *p; int r, g, b, y, u, v, tmp; while (isspace(*line)) ++line; p = line; while (isxdigit(*p)) ++p; if (p - line != 6) return -1; tmp = strtoul(line, NULL, 16); r = tmp >> 16 & 0xff; g = tmp >> 8 & 0xff; b = tmp & 0xff; y = MIN(MAX((int)(0.1494 * r + 0.6061 * g + 0.2445 * b), 0), 0xff); u = MIN(MAX((int)(0.6066 * r - 0.4322 * g - 0.1744 * b) + 128, 0), 0xff); v = MIN(MAX((int)(-0.08435 * r - 0.3422 * g + 0.4266 * b) + 128, 0), 0xff); vob->palette[n++] = y << 16 | u << 8 | v; if (n == 16) break; if (*p == ',') ++p; line = p; } vob->have_palette = 1; return 0;}static intvobsub_parse_custom(vobsub_t *vob, const char *line){ //custom colors: OFF/ON(0/1) if ((strncmp("ON", line + 15, 2) == 0)||strncmp("1", line + 15, 1) == 0) vob->custom=1; else if ((strncmp("OFF", line + 15, 3) == 0)||strncmp("0", line + 15, 1) == 0) vob->custom=0; else return -1; return 0;}static intvobsub_parse_cuspal(vobsub_t *vob, const char *line){ //colors: XXXXXX, XXXXXX, XXXXXX, XXXXXX unsigned int n; n = 0; line += 40; while(1){ const char *p; while (isspace(*line)) ++line; p=line; while (isxdigit(*p)) ++p; if (p - line !=6) return -1; vob->cuspal[n++] = strtoul(line, NULL,16); if (n==4) break; if(*p == ',') ++p; line = p; } return 0;}/* don't know how to use tridx */static intvobsub_parse_tridx(const char *line){ //tridx: XXXX int tridx; tridx = strtoul((line + 26), NULL, 16); tridx = ((tridx&0x1000)>>12) | ((tridx&0x100)>>7) | ((tridx&0x10)>>2) | ((tridx&1)<<3); return tridx;}static intvobsub_parse_delay(vobsub_t *vob, const char *line){ int h, m, s, ms; int forward = 1; if (*(line + 7) == '+'){ forward = 1; line++; } else if (*(line + 7) == '-'){ forward = -1; line++; } mp_msg(MSGT_SPUDEC,MSGL_V, "forward=%d", forward); h = atoi(line + 7); mp_msg(MSGT_VOBSUB,MSGL_V, "h=%d," ,h); m = atoi(line + 10); mp_msg(MSGT_VOBSUB,MSGL_V, "m=%d,", m); s = atoi(line + 13); mp_msg(MSGT_VOBSUB,MSGL_V, "s=%d,", s); ms = atoi(line + 16); mp_msg(MSGT_VOBSUB,MSGL_V, "ms=%d", ms); vob->delay = (ms + 1000 * (s + 60 * (m + 60 * h))) * forward; return 0;}static intvobsub_set_lang(const char *line){ if (vobsub_id == -1) vobsub_id = atoi(line + 8); return 0;}static intvobsub_parse_forced_subs(vobsub_t *vob, const char *line){ const char *p; p = line; while (isspace(*p)) ++p; if (strncasecmp("on",p,2) == 0){ vob->forced_subs=~0; return 0; } else if (strncasecmp("off",p,3) == 0){ vob->forced_subs=0; return 0; } return -1;}static intvobsub_parse_one_line(vobsub_t *vob, rar_stream_t *fd){ ssize_t line_size; int res = -1; size_t line_reserve = 0; char *line = NULL; do { line_size = getline(&line, &line_reserve, fd); if (line_size < 0) { break; } if (*line == 0 || *line == '\r' || *line == '\n' || *line == '#') continue; else if (strncmp("langidx:", line, 8) == 0) res = vobsub_set_lang(line); else if (strncmp("delay:", line, 6) == 0) res = vobsub_parse_delay(vob, line); else if (strncmp("id:", line, 3) == 0) res = vobsub_parse_id(vob, line + 3); else if (strncmp("palette:", line, 8) == 0) res = vobsub_parse_palette(vob, line + 8); else if (strncmp("size:", line, 5) == 0) res = vobsub_parse_size(vob, line + 5); else if (strncmp("org:", line, 4) == 0) res = vobsub_parse_origin(vob, line + 4); else if (strncmp("timestamp:", line, 10) == 0) res = vobsub_parse_timestamp(vob, line + 10); else if (strncmp("custom colors:", line, 14) == 0) //custom colors: ON/OFF, tridx: XXXX, colors: XXXXXX, XXXXXX, XXXXXX,XXXXXX res = vobsub_parse_cuspal(vob, line) + vobsub_parse_tridx(line) + vobsub_parse_custom(vob, line); else if (strncmp("forced subs:", line, 12) == 0) res = vobsub_parse_forced_subs(vob, line + 12); else { mp_msg(MSGT_VOBSUB,MSGL_V, "vobsub: ignoring %s", line); continue; } if (res < 0) mp_msg(MSGT_VOBSUB,MSGL_ERR, "ERROR in %s", line); break; } while (1); if (line) free(line); return res;}intvobsub_parse_ifo(void* this, const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force, int sid, char *langid){ vobsub_t *vob = (vobsub_t*)this; int res = -1; rar_stream_t *fd = rar_open(name, "rb"); if (fd == NULL) { if (force) mp_msg(MSGT_VOBSUB,MSGL_ERR, "VobSub: Can't open IFO file\n"); } else { // parse IFO header unsigned char block[0x800]; const char *const ifo_magic = "DVDVIDEO-VTS"; if (rar_read(block, sizeof(block), 1, fd) != 1) { if (force) mp_msg(MSGT_VOBSUB,MSGL_ERR, "VobSub: Can't read IFO header\n"); } else if (memcmp(block, ifo_magic, strlen(ifo_magic) + 1)) mp_msg(MSGT_VOBSUB,MSGL_ERR, "VobSub: Bad magic in IFO header\n"); else { unsigned long pgci_sector = block[0xcc] << 24 | block[0xcd] << 16 | block[0xce] << 8 | block[0xcf]; int standard = (block[0x200] & 0x30) >> 4; int resolution = (block[0x201] & 0x0c) >> 2; *height = standard ? 576 : 480; *width = 0; switch (resolution) { case 0x0: *width = 720; break; case 0x1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -