55typedef int8_t
ei8;
typedef uint8_t
eu8;
59typedef int_least8_t
li8;
typedef uint_least8_t
lu8;
60typedef int_least16_t
li16;
typedef uint_least16_t
lu16;
61typedef int_least32_t
li32;
typedef uint_least32_t
lu32;
63typedef int_fast8_t
fi8;
typedef uint_fast8_t
fu8;
64typedef int_fast16_t
fi16;
typedef uint_fast16_t
fu16;
65typedef int_fast32_t
fi32;
typedef uint_fast32_t
fu32;
69#define GCCATTR_PRINTF(m, n) __attribute__ ((format (printf, m, n)))
70#define GCCATTR_UNUSED __attribute ((unused))
71#define GCCATTR_NORETURN __attribute ((noreturn))
72#define GCCATTR_CONST __attribute ((const))
75#define CUS (const unsigned char *)
79int sup2dast(
const char *supfile,
const char *ifofile,
int delay_ms);
100#define exc_try(x) do { struct exc__state exc_s##x; int exc_type##x GCCATTR_UNUSED; \
101 exc_s##x.m_prev = EXC.m_last; \
102 EXC.m_last = &exc_s##x; \
103 exc_type##x = setjmp(exc_s##x.m_env); \
104 if (exc_type##x == 0)
106#define exc_ftry(x) do { struct exc__state exc_s##x, *exc_p##x = EXC.m_last; \
107 int exc_type##x GCCATTR_UNUSED; \
108 exc_s##x.prev = EXC.m_last; \
109 EXC.m_last = &exc_s##x; \
110 exc_type##x = setjmp(exc_s##x.env); \
111 if (exc_type##x == 0)
113#define exc_catch(x,t) else if ((t) == exc_type##x)
115#define exc_end(x) else __exc_throw(exc_type##x); EXC.m_last = exc_s##x.m_prev; } while (0)
117#define exc_return(x) for (EXC.m_last = exc_p##x;) return
119#define exc_fthrow(x) for (EXC.m_last = exc_p##x;) ex_throw
121#define exc_catchall else
122#define exc_endall(x) EXC.m_last = exc_s##x.m_prev; } while (0)
124#define exc_cleanup() EXC.m_last = NULL;
129 EXC.m_last =
EXC.m_last->m_prev;
140 va_start(ap, format);
141 unsigned int len = vsnprintf(
EXC.m_msgbuf,
sizeof EXC.m_msgbuf, format, ap);
144 if (len >=
sizeof EXC.m_msgbuf)
146 len =
sizeof EXC.m_msgbuf - 1;
147 EXC.m_msgbuf[len] =
'\0';
151 if (format[strlen(format) - 1] ==
':')
153 int l = snprintf(&
EXC.m_msgbuf[len],
sizeof EXC.m_msgbuf - len,
154 " %s.", strerror(err));
155 if (l + len >=
sizeof EXC.m_msgbuf)
157 len =
sizeof EXC.m_msgbuf - 1;
158 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)
217 int lr = (500 + (1164 * (y - 16)) + (1596 * (cr - 128)) ) / 1000;
218 int lg = (500 + (1164 * (y - 16)) - ( 813 * (cr - 128)) - ( 391 * (cb - 128))) / 1000;
219 int lb = (500 + (1164 * (y - 16)) + (2018 * (cb - 128))) / 1000;
221 *r =
clamp(lr, 0, 255);
222 *g =
clamp(lg, 0, 255);
223 *b =
clamp(lb, 0, 255);
232 *y = ( (257 * r) + (504 * g) + (98 * b) + 16500) / 1000;
233 *cr = ( (439 * r) - (368 * g) - (71 * b) + 128500) / 1000;
234 *cb = ((-148 * r) - (291 * g) + (439 * b) + 128500) / 1000;
264 if (fseek(stream, offset, SEEK_SET) < 0)
268static void xmkdir(
const char * path,
int mode)
275 if (mkdir(path, mode) < 0)
285 if (stat(
filename, &st) == 0 && S_ISREG(st.st_mode))
294 if (stat(
filename, &st) == 0 && S_ISDIR(st.st_mode))
331 ptr[0] = value>>24; ptr[1] = value>>16; ptr[2] = value>>8; ptr[3] =value;
335static void set_uint16_be(
eu8 * ptr,
eu32 value) {
336 ptr[0] = value>>8; ptr[1] = value; }
338static void set_uint32_le(
eu8 * ptr,
eu32 value) {
339 ptr[3] = value>>24; ptr[2] = value>>16; ptr[1] = value>>8; ptr[0] =value; }
344 ptr[1] = value>>8; ptr[0] =value;
355 eu8 yuvpalette[16][3],
eu8 rgbpalette[16][3])
360 if (memcmp(
xxfread(fh, buf, 12),
"DVDVIDEO-VTS", 12) != 0)
362 "(IFO) file %s not of type DVDVIDEO-VTS.",
filename);
366 xfseek0(fh, (offset * 0x800) + 12);
370 xxfread(fh, buf, (
size_t)(16 * 4));
372 for (
int i = 0; i < 16; i++)
377 eu8 *
p = buf + ((ptrdiff_t)i * 4) + 1;
378 yuvpalette[i][0] =
p[0]; yuvpalette[i][1] =
p[1]; yuvpalette[i][2] =
p[2];
380 rgbpalette[i][0] = r; rgbpalette[i][1] = g; rgbpalette[i][2] = b;
393 rgbpalpart[0] = r, rgbpalpart[1] = g, rgbpalpart[2] = b;
394 rgb2yuv(r, g, b, &y, &cr, &cb);
395 yuvpalpart[0] = y, yuvpalpart[1] = cr, yuvpalpart[2] = cb;
400 eu8 yuvpalette[16][3],
eu8 rgbpalette[16][3])
404 if (strlen(arg) != 20 || arg[6] !=
',' || arg[13] !=
',')
407 for (i = 0; i < 16; i++)
408 set2palettes(i * 0x111111, yuvpalette[i], rgbpalette[i]);
410 sscanf(arg,
"%x", &i);
412 sscanf(arg + 7,
"%x", &i);
414 sscanf(arg + 14,
"%x", &i);
443 const char *
filename,
int height,
int width)
455 memcpy(self->
m_buffer + 12,
"\004\003\0\0\0", 5);
464 xxfwriteCS(self->
m_fh,
"\0\0\0\001" "tRNS" "\0" "\x40\xe6\xd8\x66");
539 eu8 rv = *nibble & 0x0f;
544 *nibble = *(*data)++;
560 if ((bits & 0xc) != 0)
563 number = (bits & 0xc) >> 2;
564 cindex = bits & 0x3; }
567 bits = (bits << 4) |
getnibble(data, &nibble);
568 if ((bits & 0xf0) != 0)
571 number = (bits & 0x3c) >> 2;
576 bits = (bits << 4) |
getnibble(data, &nibble);
577 if ((bits & 0xfc0) != 0)
580 number = (bits & 0xfc) >> 2;
586 bits = (bits << 4) |
getnibble(data, &nibble);
587 number = (bits & 0x3fc) >> 2;
597 for (; number > 0 && col < width; number--, col++)
611 if (top < 0 || bot < 0)
613 printf(
"ERROR: invalid arguments to makebitmap");
616 eu8 * top_ibuf = data + top;
617 eu8 * bot_ibuf = data + bot;
622 for (
int i = 0; i < h / 2; i++)
634 uint32_t h =
pts / (3600 * 90000UL);
635 uint32_t m =
pts / (60 * 90000UL) % 60;
636 uint32_t s =
pts / 90000 % 60;
637 uint32_t hs = (
pts + 450) / 900 % 100;
640 sprintf(rvbuf,
"%02d+%02d+%02d.%02d.png", h, m, s, hs);
642 sprintf(rvbuf,
"%02d:%02d:%02d.%02d", h, m, s, hs);
675 bool createpics,
int delay_ms,
676 char * fnbuf,
char * fnbuf_fp)
681 time_t
volatile pt = 0;
682 bool volatile last =
false;
685 if (memcmp(
xxfread(sfh, data, 2),
"SP", 2) != 0)
695 eu32 volatile lastendpts = 0;
708 eu8 * ctrl = data + pack - 4;
709 xxfread(sfh, ctrl, size - pack);
713 if (memcmp(
xxfread(sfh, (
unsigned char *)junk, 2),
729 eu8 this_palette[4][3];
743 int colcon_length = 0;
754 for (
int n = 0; n < 4; n++) {
755 int i = (xpalette >> (n * 4) & 0x0f);
756 this_palette[n][0] = palette[i][0];
757 this_palette[n][1] = palette[i][1];
758 this_palette[n][2] = palette[i][2];
766 x1 = (
p[0] << 4) + (
p[1] >> 4);
767 x2 = ((
p[1] & 0xf) << 8) +
p[2];
768 y1 = (
p[3] << 4) + (
p[4] >> 4);
769 y2 = ((
p[4] & 0xf) << 8) +
p[5];
793 tmppts += delay_ms * 90;
799 eu32 endpts = tmppts + (end * 1000);
801 if (tmppts <= lastendpts)
803 if (lastendpts < endpts)
805 pts = lastendpts + (2 * (1000 / 30) * 90);
808 tmppts += delay_ms * 90;
809 printf(
"Fixed overlapping subtitle!\n");
813 printf(
"Dropping overlapping subtitle\n");
821 pts2ts(tmppts, sptsstr + 1,
false);
828 size_t len =
write(1, sptsstr, strlen(sptsstr));
829 if (len != strlen(sptsstr))
830 printf(
"ERROR: write failed");
833 fprintf(ofh,
" <spu start=\"%s\" end=\"%s\" image=\"%s\""
834 " xoffset=\"%d\" yoffset=\"%d\" />\n",
835 sptsstr + 1,
pts2ts(endpts, junk,
false),
840 bot_field - 4, fnbuf, this_palette);
848 size_t len =
write(1, sptsstr, strlen(sptsstr));
849 if (len != strlen(sptsstr))
850 printf(
"ERROR: write failed");
862 "Usage: %s [--delay ms] <supfile> <ifofile>|<palette>" "\n"
866 "\t ProjectX decoded recording.sup and recording.sup.IFO" "\n"
868 "\t\t$ pxsup2dast recording.sup*" "\n"
870 "\t Having test.sup and map.ifo" "\n"
872 "\t\t$ pxsup2dast test.sup map.ifo" "\n"
874 "\t No .IFO, so giving 3 colors (rgb components in hex)" "\n"
876 "\t\t$ pxsup2dast titles.sup ff0000,00ff00,0000ff" "\n"
878 "\t Trying to fix sync in recording" "\n"
880 "\t\t$ pxsup2dast --delay 750 recording.sup*" "\n"
891 for (
int i = 0; i < 16; i++)
896 if (fscanf(fh,
"%02x%02x%02x\n", &r, &g, &b) != 3 ||
897 r != palette[i][0] || g != palette[i][1] || b != palette[i][2])
907int sup2dast(
const char *supfile,
const char *ifofile ,
int delay_ms)
912 eu8 yuvpalette[16][3];
913 eu8 rgbpalette[16][3];
917 bool createpics =
false;
919 memset(yuvpalette, 0,
sizeof(yuvpalette));
920 memset(rgbpalette, 0,
sizeof(rgbpalette));
922 if (
write(1,
"\n", 1) != 1)
923 printf(
"ERROR: write failed");
925 if (
sizeof (
char) != 1 ||
sizeof (
int) < 2)
928 p = strrchr(supfile,
'.');
935 "not manage filenames longer than 950 characters.");
936 memcpy(fnbuf, supfile, i);
949 strcpy(
p,
"palette.ycrcb");
953 printf(
"Found palette.yuv having our palette information...\n");
954 printf(
"...Skipping image files, Writing spumux.tmp.\n");
959 printf(
"Writing image files and spumux.tmp.\n");
962 strcpy(
p,
"spumux.tmp");
966 pxsubtitle(supfile, fh, rgbpalette, createpics, delay_ms, fnbuf,
p);
968 if (
write(1,
"\n", 1) != 1)
969 printf(
"ERROR: write failed");
971 xxfwriteCS(fh,
" </stream>\n</subpictures>\n");
976 printf(
"Writing palette.ycrcb and palette.rgb.\n");
977 strcpy(
p,
"palette.ycrcb");
979 strcpy(
p,
"palette.rgb");
981 for (i = 0; i < 16; i++)
983 fprintf(yuvfh,
"%02x%02x%02x\n",
984 yuvpalette[i][0], yuvpalette[i][1], yuvpalette[i][2]);
985 fprintf(rgbfh,
"%02x%02x%02x\n",
986 rgbpalette[i][0], rgbpalette[i][1], rgbpalette[i][2]);
994 printf(
"Renaming spumux.tmp to spumux.xml.\n");
995 strcpy(
p,
"spumux.tmp");
997 memcpy(buf, fnbuf, i);
998 strcpy(&buf[i - 3],
"xml");
1003 printf(
"Output files reside in %s\n", fnbuf);
1004 printf(
"All done.\n");
1010 printf(
"ERROR: write failed");
1012 if (
write(2,
"\n", 1) != 1)
1013 printf(
"ERROR: write failed");
static uint32_t crc32(const unsigned char *data, int len)
static std::vector< uint32_t > pixel
--------------------------------------------------—**
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
def write(text, progress=True)
static void set_uint32_be(eu8 *ptr, eu32 value)
static char * pts2ts(fu32 pts, char *rvbuf, bool is_png_filename)
static bool fexists(const char *filename)
static fu32 get_uint32_le(const eu8 *bytes)
static GCCATTR_NORETURN void __exc_throw(int type)
static eu8 * boundstr_read(BoundStr *bs, int l)
static void png4file_close(Png4File *self)
struct exc__state * m_last
static bool samepalette(char *filename, eu8 palette[16][3])
static void yuv2rgb(int y, int cr, int cb, eu8 *r, eu8 *g, eu8 *b)
static void xxfwrite(FILE *stream, const eu8 *ptr, size_t size)
static void png4file_init(Png4File *self, eu8 palette[4][3])
static void ifopalette(const char *filename, eu8 yuvpalette[16][3], eu8 rgbpalette[16][3])
static void png4file_open(Png4File *self, const char *filename, int height, int width)
static void boundstr_init(BoundStr *bs, eu8 *p, int l)
static fu32 get_uint32_be(const eu8 *bytes)
static void rgb2yuv(eu8 r, eu8 g, eu8 b, eu8 *y, eu8 *cr, eu8 *cb)
static bool dexists(const char *filename)
static void set2palettes(int value, eu8 *yuvpalpart, eu8 *rgbpalpart)
static void argpalette(const char *arg, eu8 yuvpalette[16][3], eu8 rgbpalette[16][3])
static eu8 getnibble(eu8 **data, int *nibble)
static void pxsubtitle(const char *supfile, FILE *ofh, eu8 palette[16][3], bool createpics, int delay_ms, char *fnbuf, char *fnbuf_fp)
static void xfseek0(FILE *stream, long offset)
static GCCATTR_NORETURN void exc_throw(int type, const char *format,...)
static void png4file_flush(Png4File *self)
static void makebitmap(eu8 *data, int w, int h, int top, int bot, char *filename, eu8 palette[4][3])
static void xmkdir(const char *path, int mode)
int sup2dast(const char *supfile, const char *ifofile, int delay_ms)
static void png4file_endrow(Png4File *self)
static eu8 * xxfread(FILE *stream, eu8 *ptr, size_t size)
static FILE * xfopen(const char *filename, const char *mode)
static void xxfwrite_uint32_be(FILE *fh, eu32 value)
static void getpixelline(eu8 **data, int width, Png4File *picfile)
static void set_uint16_le(eu8 *ptr, eu16 value)
static fu16 get_uint16_be(const eu8 *bytes)
static eu8 clamp(eu8 value, eu8 low, eu8 high)
static void png4file_addpixel(Png4File *self, eu8 pixel)
static void usage(char *progname)
struct exc__state * m_prev