30 typedef enum {
false = 0,
true = 1 }
bool;
40 #include <sys/types.h>
55 typedef int8_t
ei8;
typedef uint8_t
eu8;
59 typedef int_least8_t
li8;
typedef uint_least8_t
lu8;
60 typedef int_least16_t
li16;
typedef uint_least16_t
lu16;
61 typedef int_least32_t
li32;
typedef uint_least32_t
lu32;
63 typedef int_fast8_t
fi8;
typedef uint_fast8_t
fu8;
64 typedef int_fast16_t
fi16;
typedef uint_fast16_t
fu16;
65 typedef int_fast32_t
fi32;
typedef uint_fast32_t
fu32;
70 #define GCCATTR_PRINTF(m, n) __attribute__ ((format (printf, m, n)))
71 #define GCCATTR_UNUSED __attribute ((unused))
72 #define GCCATTR_NORETURN __attribute ((noreturn))
73 #define GCCATTR_CONST __attribute ((const))
75 #define GCCATTR_PRINTF(m, n)
76 #define GCCATTR_UNUSED
77 #define GCCATTR_NORETURN
82 #define CUS (const unsigned char *)
86 int sup2dast(
const char *supfile,
const char *ifofile,
int delay_ms);
107 #define exc_try(x) do { struct exc__state exc_s##x; int exc_type##x GCCATTR_UNUSED; \
108 exc_s##x.m_prev = EXC.m_last; EXC.m_last = &exc_s##x; if ((exc_type##x = setjmp(exc_s##x.m_env)) == 0)
110 #define exc_ftry(x) do { struct exc__state exc_s##x, *exc_p##x = EXC.m_last; \
111 int exc_type##x GCCATTR_UNUSED; exc_s##x.prev = EXC.m_last; \
112 EXC.m_last = &exc_s##x; if ((exc_type##x = setjmp(exc_s##x.env)) == 0)
114 #define exc_catch(x,t) else if ((t) == exc_type##x)
116 #define exc_end(x) else __exc_throw(exc_type##x); EXC.m_last = exc_s##x.m_prev; } while (0)
118 #define exc_return(x) for (EXC.m_last = exc_p##x;) return
120 #define exc_fthrow(x) for (EXC.m_last = exc_p##x;) ex_throw
122 #define exc_catchall else
123 #define exc_endall(x) EXC.m_last = exc_s##x.m_prev; } while (0)
125 #define exc_cleanup() EXC.m_last = NULL;
130 EXC.m_last =
EXC.m_last->m_prev;
142 va_start(ap, format);
143 unsigned int len = vsnprintf(
EXC.m_msgbuf,
sizeof EXC.m_msgbuf, format, ap);
146 if (len >=
sizeof EXC.m_msgbuf)
148 len =
sizeof EXC.m_msgbuf - 1;
149 EXC.m_msgbuf[len] =
'\0';
153 if (format[strlen(format) - 1] ==
':')
155 int l = snprintf(&
EXC.m_msgbuf[len],
sizeof EXC.m_msgbuf - len,
156 " %s.", strerror(err));
157 if (l + len >=
sizeof EXC.m_msgbuf)
159 len =
sizeof EXC.m_msgbuf - 1;
160 EXC.m_msgbuf[len] =
'\0';
170 EXC.m_msgbuf[0] =
'\0';
182 size_t n = fread(ptr, size, 1, stream);
193 size_t n = fwrite(ptr, size, 1, stream);
202 #define xxfwriteCS(f, s) xxfwrite(f, CUS s, sizeof (s) - 1)
208 int lr = (500 + 1164 * (y - 16) + 1596 * (cr - 128) ) /1000;
209 int lg = (500 + 1164 * (y - 16) - 813 * (cr - 128) - 391 * (cb - 128)) / 1000;
210 int lb = (500 + 1164 * (y - 16) + 2018 * (cb - 128)) / 1000;
212 *r = (lr < 0)? 0: (lr > 255)? 255: (
eu8)lr;
213 *g = (lg < 0)? 0: (lg > 255)? 255: (
eu8)lg;
214 *b = (lb < 0)? 0: (lb > 255)? 255: (
eu8)lb;
223 *y = ( 257 * r + 504 * g + 98 * b + 16500) / 1000;
224 *cr = ( 439 * r - 368 * g - 71 * b + 128500) / 1000;
225 *cb = (-148 * r - 291 * g + 439 * b + 128500) / 1000;
255 if (fseek(stream, offset, SEEK_SET) < 0)
259 static void xmkdir(
const char * path,
int mode)
266 if (mkdir(path, mode) < 0)
276 if (stat(
filename, &st) == 0 && S_ISREG(st.st_mode))
285 if (stat(
filename, &st) == 0 && S_ISDIR(st.st_mode))
314 ptr[0] = value>>24; ptr[1] = value>>16; ptr[2] = value>>8; ptr[3] =value;
318 static void set_uint16_be(
eu8 * ptr,
eu32 value) {
319 ptr[0] = value>>8; ptr[1] = value; }
321 static void set_uint32_le(
eu8 * ptr,
eu32 value) {
322 ptr[3] = value>>24; ptr[2] = value>>16; ptr[1] = value>>8; ptr[0] =value; }
327 ptr[1] = value>>8; ptr[0] =value;
338 eu8 yuvpalette[16][3],
eu8 rgbpalette[16][3])
343 if (memcmp(
xxfread(fh, buf, 12),
"DVDVIDEO-VTS", 12) != 0)
345 "(IFO) file %s not of type DVDVIDEO-VTS.",
filename);
349 xfseek0(fh, offset * 0x800 + 12);
353 xxfread(fh, buf, (
size_t)(16 * 4));
355 for (
int i = 0; i < 16; i++)
360 eu8 *
p = buf + (ptrdiff_t)(i) * 4 + 1;
361 yuvpalette[i][0] =
p[0]; yuvpalette[i][1] =
p[1]; yuvpalette[i][2] =
p[2];
363 rgbpalette[i][0] = r; rgbpalette[i][1] = g; rgbpalette[i][2] = b;
376 rgbpalpart[0] = r, rgbpalpart[1] = g, rgbpalpart[2] = b;
377 rgb2yuv(r, g, b, &y, &cr, &cb);
378 yuvpalpart[0] = y, yuvpalpart[1] = cr, yuvpalpart[2] = cb;
383 eu8 yuvpalette[16][3],
eu8 rgbpalette[16][3])
387 if (strlen(arg) != 20 || arg[6] !=
',' || arg[13] !=
',')
390 for (i = 0; i < 16; i++)
391 set2palettes(i * 0x111111, yuvpalette[i], rgbpalette[i]);
393 sscanf(arg,
"%x", &i);
395 sscanf(arg + 7,
"%x", &i);
397 sscanf(arg + 14,
"%x", &i);
418 memcpy(self->m_paletteChunk,
"\0\0\0\x0c" "PLTE", 8);
419 memcpy(self->m_paletteChunk + 8, palette, 12);
421 self->m_crc =
crc32(self->m_crc, self->m_paletteChunk + 4, 16);
426 const char *
filename,
int height,
int width)
429 self->m_width = width;
430 self->m_hleft = height;
433 xxfwrite(self->m_fh,
CUS "\x89PNG\r\n\x1a\n" "\0\0\0\x0d", 12);
435 memcpy(self->m_buffer,
"IHDR", 4);
438 memcpy(self->m_buffer + 12,
"\004\003\0\0\0", 5);
442 xxfwrite(self->m_fh, self->m_buffer, 21);
444 xxfwrite(self->m_fh, self->m_paletteChunk,
sizeof self->m_paletteChunk);
447 xxfwriteCS(self->m_fh,
"\0\0\0\001" "tRNS" "\0" "\x40\xe6\xd8\x66");
449 xxfwrite(self->m_fh,
CUS "\0\0\0\0IDAT" "\x78\001", 10);
450 self->m_buffer[0] =
'\0';
451 self->m_buffer[5] =
'\0';
453 self->m_chunkLen = 2;
454 self->m_crc =
crc32(0,
CUS "IDAT" "\x78\001", 6);
460 int l =
self->m_bufPos - 5;
461 self->m_chunkLen +=
self->m_bufPos;
464 xxfwrite(self->m_fh, self->m_buffer, self->m_bufPos);
465 self->m_crc =
crc32(self->m_crc, self->m_buffer, self->m_bufPos);
466 self->m_adler = adler32(self->m_adler, self->m_buffer + 5, self->m_bufPos - 5);
467 self->m_buffer[0] =
'\0';
473 if (self->m_nibble < 0)
474 self->m_nibble = (
pixel << 4);
477 self->m_buffer[
self->m_bufPos++] =
self->m_nibble |
pixel;
479 if (self->m_bufPos ==
sizeof self->m_buffer - 4)
486 if (self->m_nibble >= 0)
488 self->m_buffer[
self->m_bufPos++] =
self->m_nibble;
494 self->m_buffer[
self->m_bufPos++] =
'\0';
500 self->m_buffer[0] = 0x01;
511 self->m_crc =
crc32(self->m_crc, adlerbuf, 4);
513 xxfwriteCS(self->m_fh,
"\0\0\0\0" "IEND" "\xae\x42\x60\x82");
524 eu8 rv = *nibble & 0x0f;
529 *nibble = *(*data)++;
545 if ((bits & 0xc) != 0)
548 number = (bits & 0xc) >> 2;
549 cindex = bits & 0x3; }
552 bits = (bits << 4) |
getnibble(data, &nibble);
553 if ((bits & 0xf0) != 0)
556 number = (bits & 0x3c) >> 2;
561 bits = (bits << 4) |
getnibble(data, &nibble);
562 if ((bits & 0xfc0) != 0)
565 number = (bits & 0xfc) >> 2;
571 bits = (bits << 4) |
getnibble(data, &nibble);
572 number = (bits & 0x3fc) >> 2;
582 for (; number > 0 && col < width; number--, col++)
596 eu8 * top_ibuf = data + top;
597 eu8 * bot_ibuf = data + bot;
602 for (
int i = 0; i < h / 2; i++)
614 uint32_t h =
pts / (3600 * 90000UL);
615 uint32_t m =
pts / (60 * 90000UL) % 60;
616 uint32_t s =
pts / 90000 % 60;
617 uint32_t hs = (
pts + 450) / 900 % 100;
620 sprintf(rvbuf,
"%02d+%02d+%02d.%02d.png", h, m, s, hs);
622 sprintf(rvbuf,
"%02d:%02d:%02d.%02d", h, m, s, hs);
655 bool createpics,
int delay_ms,
656 char * fnbuf,
char * fnbuf_fp)
661 time_t
volatile pt = 0;
662 bool volatile last =
false;
665 if (memcmp(
xxfread(sfh, data, 2),
"SP", 2) != 0)
675 eu32 volatile lastendpts = 0;
688 eu8 * ctrl = data + pack - 4;
689 xxfread(sfh, ctrl, size - pack);
693 if (memcmp(
xxfread(sfh, (
unsigned char *)junk, 2),
709 eu8 this_palette[4][3];
723 int colcon_length = 0;
734 for (
int n = 0; n < 4; n++) {
735 int i = (xpalette >> (n * 4) & 0x0f);
736 this_palette[n][0] = palette[i][0];
737 this_palette[n][1] = palette[i][1];
738 this_palette[n][2] = palette[i][2];
746 x1 = (
p[0] << 4) + (
p[1] >> 4);
747 x2 = ((
p[1] & 0xf) << 8) +
p[2];
748 y1 = (
p[3] << 4) + (
p[4] >> 4);
749 y2 = ((
p[4] & 0xf) << 8) +
p[5];
773 tmppts += delay_ms * 90;
779 eu32 endpts = tmppts + end * 1000;
781 if (tmppts <= lastendpts)
783 if (lastendpts < endpts)
785 pts = lastendpts + 2 * (1000 / 30) * 90;
788 tmppts += delay_ms * 90;
789 printf(
"Fixed overlapping subtitle!\n");
793 printf(
"Dropping overlapping subtitle\n");
801 pts2ts(tmppts, sptsstr + 1,
false);
808 size_t len =
write(1, sptsstr, strlen(sptsstr));
809 if (len != strlen(sptsstr))
810 printf(
"ERROR: write failed");
813 fprintf(ofh,
" <spu start=\"%s\" end=\"%s\" image=\"%s\""
814 " xoffset=\"%d\" yoffset=\"%d\" />\n",
815 sptsstr + 1,
pts2ts(endpts, junk,
false),
820 bot_field - 4, fnbuf, this_palette);
828 size_t len =
write(1, sptsstr, strlen(sptsstr));
829 if (len != strlen(sptsstr))
830 printf(
"ERROR: write failed");
838 static void usage(
const char * pn)
841 "Usage: %s [--delay ms] <supfile> <ifofile>|<palette>" "\n"
845 "\t ProjectX decoded recording.sup and recording.sup.IFO" "\n"
847 "\t\t$ pxsup2dast recording.sup*" "\n"
849 "\t Having test.sup and map.ifo" "\n"
851 "\t\t$ pxsup2dast test.sup map.ifo" "\n"
853 "\t No .IFO, so giving 3 colors (rgb components in hex)" "\n"
855 "\t\t$ pxsup2dast titles.sup ff0000,00ff00,0000ff" "\n"
857 "\t Trying to fix sync in recording" "\n"
859 "\t\t$ pxsup2dast --delay 750 recording.sup*" "\n"
870 for (
int i = 0; i < 16; i++)
875 if (fscanf(fh,
"%02x%02x%02x\n", &r, &g, &b) != 3 ||
876 r != palette[i][0] || g != palette[i][1] || b != palette[i][2])
886 int sup2dast(
const char *supfile,
const char *ifofile ,
int delay_ms)
891 eu8 yuvpalette[16][3];
892 eu8 rgbpalette[16][3];
896 bool createpics =
false;
898 memset(yuvpalette, 0,
sizeof(yuvpalette));
899 memset(rgbpalette, 0,
sizeof(rgbpalette));
901 if (
write(1,
"\n", 1) != 1)
902 printf(
"ERROR: write failed");
904 if (
sizeof (
char) != 1 ||
sizeof (
int) < 2)
907 if ((
p = strrchr(supfile,
'.')) != NULL)
913 "not manage filenames longer than 950 characters.");
914 memcpy(fnbuf, supfile, i);
927 strcpy(
p,
"palette.ycrcb");
931 printf(
"Found palette.yuv having our palette information...\n");
932 printf(
"...Skipping image files, Writing spumux.tmp.\n");
937 printf(
"Writing image files and spumux.tmp.\n");
940 strcpy(
p,
"spumux.tmp");
944 pxsubtitle(supfile, fh, rgbpalette, createpics, delay_ms, fnbuf,
p);
946 if (
write(1,
"\n", 1) != 1)
947 printf(
"ERROR: write failed");
949 xxfwriteCS(fh,
" </stream>\n</subpictures>\n");
954 printf(
"Writing palette.ycrcb and palette.rgb.\n");
955 strcpy(
p,
"palette.ycrcb");
957 strcpy(
p,
"palette.rgb");
959 for (i = 0; i < 16; i++)
961 fprintf(yuvfh,
"%02x%02x%02x\n",
962 yuvpalette[i][0], yuvpalette[i][1], yuvpalette[i][2]);
963 fprintf(rgbfh,
"%02x%02x%02x\n",
964 rgbpalette[i][0], rgbpalette[i][1], rgbpalette[i][2]);
972 printf(
"Renaming spumux.tmp to spumux.xml.\n");
973 strcpy(
p,
"spumux.tmp");
975 memcpy(buf, fnbuf, i);
976 strcpy(&buf[i - 3],
"xml");
981 printf(
"Output files reside in %s\n", fnbuf);
982 printf(
"All done.\n");
988 printf(
"ERROR: write failed");
990 if (
write(2,
"\n", 1) != 1)
991 printf(
"ERROR: write failed");