diff --git a/src/zm.h b/src/zm.h index a60ab655d..0c780b244 100644 --- a/src/zm.h +++ b/src/zm.h @@ -26,8 +26,8 @@ #include "zm_config.h" #ifdef SOLARIS -#undef DEFAULT_TYPE // pthread defines this which breaks StreamType DEFAULT_TYPE -#include // define strerror() and friends +#undef DEFAULT_TYPE // pthread defines this which breaks StreamType DEFAULT_TYPE +#include // define strerror() and friends #endif #include "zm_logger.h" diff --git a/src/zm_bigfont.h b/src/zm_bigfont.h index b653a7f4f..96ba479dd 100644 --- a/src/zm_bigfont.h +++ b/src/zm_bigfont.h @@ -1,6155 +1,6155 @@ /***********************************************************/ -/* */ -/* Font file generated by schrorg */ -/* based on the font file generated by rthelen */ -/* using utils/mk_bigfont.pl */ -/* */ +/* */ +/* Font file generated by schrorg */ +/* based on the font file generated by rthelen */ +/* using utils/mk_bigfont.pl */ +/* */ /***********************************************************/ static unsigned int bigfontdata[] = { - /* 0 0x00 '^A' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 1 0x01 '^B' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 2 0x02 '^C' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 3 0x03 '^D' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 4 0x04 '^E' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 5 0x05 '^F' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 6 0x06 '^G' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 7 0x07 '^H' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 8 0x08 '^I' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 9 0x09 '^J' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 10 0x0a '^K' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 11 0x0b '^L' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 12 0x0c '^M' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 13 0x0d '^N' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 14 0x0e '^O' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 15 0x0f '^P' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 16 0x10 '^Q' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 17 0x11 '^R' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 18 0x12 '^S' */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 19 0x13 '^T' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 20 0x14 '^U' */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 21 0x15 '^V' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 22 0x16 '^W' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 23 0x17 '^X' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 24 0x18 '^Y' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 25 0x19 '^Z' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 26 0x1a '^[' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 27 0x1b '^\' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 28 0x1c '^]' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 29 0x1d '^^' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 30 0x1e '^_' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 31 0x1f '^`' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 32 0x20 ' ' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 33 0x21 '!' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 34 0x22 '"' */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 35 0x23 '#' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 36 0x24 '$' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 37 0x25 '%' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 38 0x26 '&' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 39 0x27 ''' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 40 0x28 '(' */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 41 0x29 ')' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 42 0x2a '*' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 43 0x2b '+' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 44 0x2c ',' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 45 0x2d '-' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 46 0x2e '.' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 47 0x2f '/' */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 48 0x30 '0' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 49 0x31 '1' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3f0, /* 000000 0000 */ - 0x3f0, /* 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 50 0x32 '2' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 51 0x33 '3' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 52 0x34 '4' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3f0, /* 000000 0000 */ - 0x3f0, /* 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 53 0x35 '5' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 54 0x36 '6' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 55 0x37 '7' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 56 0x38 '8' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 57 0x39 '9' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 58 0x3a ':' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 59 0x3b ';' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 60 0x3c '<' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 61 0x3d '=' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 62 0x3e '>' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 63 0x3f '?' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 64 0x40 '@' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3f30, /* 00 00 0000 */ - 0x3f30, /* 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 65 0x41 'A' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 66 0x42 'B' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 67 0x43 'C' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 68 0x44 'D' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 69 0x45 'E' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 70 0x46 'F' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 71 0x47 'G' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 72 0x48 'H' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 73 0x49 'I' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 74 0x4a 'J' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 75 0x4b 'K' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3c00, /* 00 0000000000 */ - 0x3c00, /* 00 0000000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 76 0x4c 'L' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 77 0x4d 'M' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 78 0x4e 'N' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 79 0x4f 'O' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 80 0x50 'P' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 81 0x51 'Q' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 82 0x52 'R' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 83 0x53 'S' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 84 0x54 'T' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 85 0x55 'U' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 86 0x56 'V' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 87 0x57 'W' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 88 0x58 'X' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 89 0x59 'Y' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 90 0x5a 'Z' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 91 0x5b '[' */ - 0xf0, /* 00000000 0000 */ - 0xf0, /* 00000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xf0, /* 00000000 0000 */ - 0xf0, /* 00000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 92 0x5c '\' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc, /* 000000000000 00 */ - 0xc, /* 000000000000 00 */ - 0xc, /* 000000000000 00 */ - 0xc, /* 000000000000 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 93 0x5d ']' */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 94 0x5e '^' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 95 0x5f '_' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ffc, /* 00 00 */ - 0x3ffc, /* 00 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 96 0x60 '`' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 97 0x61 'a' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 98 0x62 'b' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 99 0x63 'c' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 100 0x64 'd' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 101 0x65 'e' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 102 0x66 'f' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf0, /* 00000000 0000 */ - 0xf0, /* 00000000 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 103 0x67 'g' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 104 0x68 'h' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 105 0x69 'i' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 106 0x6a 'j' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3c00, /* 00 0000000000 */ - 0x3c00, /* 00 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 107 0x6b 'k' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3f00, /* 00 00000000 */ - 0x3f00, /* 00 00000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 108 0x6c 'l' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 109 0x6d 'm' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 110 0x6e 'n' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 111 0x6f 'o' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 112 0x70 'p' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 113 0x71 'q' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 114 0x72 'r' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 115 0x73 's' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 116 0x74 't' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xf0, /* 00000000 0000 */ - 0xf0, /* 00000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 117 0x75 'u' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 118 0x76 'v' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 119 0x77 'w' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 120 0x78 'x' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 121 0x79 'y' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 122 0x7a 'z' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 123 0x7b '{' */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 124 0x7c '|' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 125 0x7d '}' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 126 0x7e '~' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 127 0x7f '^?' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 128 0x80 '\200' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 129 0x81 '\201' */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 130 0x82 '\202' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 131 0x83 '\203' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 132 0x84 '\204' */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 133 0x85 '\205' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 134 0x86 '\206' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 135 0x87 '\207' */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 136 0x88 '\210' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 137 0x89 '\211' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 138 0x8a '\212' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 139 0x8b '\213' */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 140 0x8c '\214' */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 141 0x8d '\215' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 142 0x8e '\216' */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 143 0x8f '\217' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 144 0x90 '\220' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 145 0x91 '\221' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 146 0x92 '\222' */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 147 0x93 '\223' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 148 0x94 '\224' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 149 0x95 '\225' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 150 0x96 '\226' */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 151 0x97 '\227' */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 152 0x98 '\230' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 153 0x99 '\231' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 154 0x9a '\232' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 155 0x9b '\233' */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 156 0x9c '\234' */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 157 0x9d '\235' */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 158 0x9e '\236' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 159 0x9f '\237' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 160 0xa0 '\240' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 161 0xa1 '\241' */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 162 0xa2 '\242' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 163 0xa3 '\243' */ - 0xf00, /* 0000 00000000 */ - 0xf00, /* 0000 00000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3f00, /* 00 00000000 */ - 0x3f00, /* 00 00000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 164 0xa4 '\244' */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 165 0xa5 '\245' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 166 0xa6 '\246' */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 167 0xa7 '\247' */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 168 0xa8 '\250' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3f00, /* 00 00000000 */ - 0x3f00, /* 00 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 169 0xa9 '\251' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3f00, /* 00 00000000 */ - 0x3f00, /* 00 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xf30, /* 0000 00 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3f00, /* 00 00000000 */ - 0x3f00, /* 00 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 170 0xaa '\252' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3fcc, /* 00 00 00 */ - 0x3fcc, /* 00 00 00 */ - 0xcfc, /* 0000 00 00 */ - 0xcfc, /* 0000 00 00 */ - 0xcfc, /* 0000 00 00 */ - 0xcfc, /* 0000 00 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 171 0xab '\253' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 172 0xac '\254' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 173 0xad '\255' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 174 0xae '\256' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3fc0, /* 00 000000 */ - 0x3fc0, /* 00 000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x33f0, /* 00 00 0000 */ - 0x33f0, /* 00 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 175 0xaf '\257' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 176 0xb0 '\260' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 177 0xb1 '\261' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 178 0xb2 '\262' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 179 0xb3 '\263' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3f0, /* 000000 0000 */ - 0x3f0, /* 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 180 0xb4 '\264' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 181 0xb5 '\265' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x3f30, /* 00 00 0000 */ - 0x3f30, /* 00 00 0000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 182 0xb6 '\266' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xf0, /* 00000000 0000 */ - 0xf0, /* 00000000 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 183 0xb7 '\267' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 184 0xb8 '\270' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 185 0xb9 '\271' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 186 0xba '\272' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3c00, /* 00 0000000000 */ - 0x3c00, /* 00 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 187 0xbb '\273' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3f0, /* 000000 0000 */ - 0x3f0, /* 000000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3f0, /* 000000 0000 */ - 0x3f0, /* 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 188 0xbc '\274' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 189 0xbd '\275' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3cf0, /* 00 00 0000 */ - 0x3cf0, /* 00 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 190 0xbe '\276' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x33f0, /* 00 00 0000 */ - 0x33f0, /* 00 00 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 191 0xbf '\277' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x30f0, /* 00 0000 0000 */ - 0x30f0, /* 00 0000 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0x3c30, /* 00 0000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 192 0xc0 '\300' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 193 0xc1 '\301' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 194 0xc2 '\302' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 195 0xc3 '\303' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xf0, /* 00000000 0000 */ - 0xf0, /* 00000000 0000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0xc00, /* 0000 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 196 0xc4 '\304' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3c00, /* 00 0000000000 */ - 0x3c00, /* 00 0000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 197 0xc5 '\305' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3000, /* 00 000000000000 */ - 0x3000, /* 00 000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 198 0xc6 '\306' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 199 0xc7 '\307' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 200 0xc8 '\310' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0xc30, /* 0000 0000 0000 */ - 0x30c0, /* 00 0000 000000 */ - 0x30c0, /* 00 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 201 0xc9 '\311' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 202 0xca '\312' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 203 0xcb '\313' */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 204 0xcc '\314' */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 205 0xcd '\315' */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 206 0xce '\316' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x33c0, /* 00 00 000000 */ - 0x33c0, /* 00 00 000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 207 0xcf '\317' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3330, /* 00 00 00 0000 */ - 0x3330, /* 00 00 00 0000 */ - 0x33f0, /* 00 00 0000 */ - 0x33f0, /* 00 00 0000 */ - 0x3300, /* 00 00 00000000 */ - 0x3300, /* 00 00 00000000 */ - 0xcf0, /* 0000 00 0000 */ - 0xcf0, /* 0000 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 208 0xd0 '\320' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 209 0xd1 '\321' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ffc, /* 00 00 */ - 0x3ffc, /* 00 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 210 0xd2 '\322' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 211 0xd3 '\323' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0x330, /* 000000 00 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 212 0xd4 '\324' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 213 0xd5 '\325' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3c0, /* 000000 000000 */ - 0x3c0, /* 000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0xc0, /* 00000000 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 214 0xd6 '\326' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ff0, /* 00 0000 */ - 0x3ff0, /* 00 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 215 0xd7 '\327' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x300, /* 000000 00000000 */ - 0x300, /* 000000 00000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 216 0xd8 '\330' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xcc0, /* 0000 00 000000 */ - 0xcc0, /* 0000 00 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0x3030, /* 00 000000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x30, /* 0000000000 0000 */ - 0x30, /* 0000000000 0000 */ - 0xfc0, /* 0000 000000 */ - 0xfc0, /* 0000 000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 217 0xd9 '\331' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ffc, /* 00 00 */ - 0x3ffc, /* 00 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ffc, /* 00 00 */ - 0x3ffc, /* 00 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x3ffc, /* 00 00 */ - 0x3ffc, /* 00 00 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 218 0xda '\332' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 219 0xdb '\333' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 220 0xdc '\334' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 221 0xdd '\335' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 222 0xde '\336' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 223 0xdf '\337' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 224 0xe0 '\340' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 225 0xe1 '\341' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 226 0xe2 '\342' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 227 0xe3 '\343' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 228 0xe4 '\344' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 229 0xe5 '\345' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 230 0xe6 '\346' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 231 0xe7 '\347' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 232 0xe8 '\350' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 233 0xe9 '\351' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 234 0xea '\352' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 235 0xeb '\353' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 236 0xec '\354' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 237 0xed '\355' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 238 0xee '\356' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 239 0xef '\357' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 240 0xf0 '\360' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 241 0xf1 '\361' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 242 0xf2 '\362' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 243 0xf3 '\363' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 244 0xf4 '\364' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 245 0xf5 '\365' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 246 0xf6 '\366' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 247 0xf7 '\367' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 248 0xf8 '\370' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 249 0xf9 '\371' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 250 0xfa '\372' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 251 0xfb '\373' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 252 0xfc '\374' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 253 0xfd '\375' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 254 0xfe '\376' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - - /* 255 0xff '\377' */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0xff0, /* 0000 0000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ - 0x0, /* 0000000000000000 */ + /* 0 0x00 '^A' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 1 0x01 '^B' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 2 0x02 '^C' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 3 0x03 '^D' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 4 0x04 '^E' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 5 0x05 '^F' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 6 0x06 '^G' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 7 0x07 '^H' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 8 0x08 '^I' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 9 0x09 '^J' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 10 0x0a '^K' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 11 0x0b '^L' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 12 0x0c '^M' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 13 0x0d '^N' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 14 0x0e '^O' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 15 0x0f '^P' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 16 0x10 '^Q' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 17 0x11 '^R' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 18 0x12 '^S' */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 19 0x13 '^T' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 20 0x14 '^U' */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 21 0x15 '^V' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 22 0x16 '^W' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 23 0x17 '^X' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 24 0x18 '^Y' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 25 0x19 '^Z' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 26 0x1a '^[' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 27 0x1b '^\' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 28 0x1c '^]' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 29 0x1d '^^' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 30 0x1e '^_' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 31 0x1f '^`' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 32 0x20 ' ' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 33 0x21 '!' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 34 0x22 '"' */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 35 0x23 '#' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 36 0x24 '$' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 37 0x25 '%' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 38 0x26 '&' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 39 0x27 ''' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 40 0x28 '(' */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 41 0x29 ')' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 42 0x2a '*' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 43 0x2b '+' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 44 0x2c ',' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 45 0x2d '-' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 46 0x2e '.' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 47 0x2f '/' */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 48 0x30 '0' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 49 0x31 '1' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3f0, /* 000000 0000 */ + 0x3f0, /* 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 50 0x32 '2' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 51 0x33 '3' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 52 0x34 '4' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3f0, /* 000000 0000 */ + 0x3f0, /* 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 53 0x35 '5' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 54 0x36 '6' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 55 0x37 '7' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 56 0x38 '8' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 57 0x39 '9' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 58 0x3a ':' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 59 0x3b ';' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 60 0x3c '<' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 61 0x3d '=' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 62 0x3e '>' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 63 0x3f '?' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 64 0x40 '@' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3f30, /* 00 00 0000 */ + 0x3f30, /* 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 65 0x41 'A' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 66 0x42 'B' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 67 0x43 'C' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 68 0x44 'D' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 69 0x45 'E' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 70 0x46 'F' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 71 0x47 'G' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 72 0x48 'H' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 73 0x49 'I' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 74 0x4a 'J' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 75 0x4b 'K' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3c00, /* 00 0000000000 */ + 0x3c00, /* 00 0000000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 76 0x4c 'L' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 77 0x4d 'M' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 78 0x4e 'N' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 79 0x4f 'O' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 80 0x50 'P' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 81 0x51 'Q' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 82 0x52 'R' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 83 0x53 'S' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 84 0x54 'T' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 85 0x55 'U' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 86 0x56 'V' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 87 0x57 'W' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 88 0x58 'X' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 89 0x59 'Y' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 90 0x5a 'Z' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 91 0x5b '[' */ + 0xf0, /* 00000000 0000 */ + 0xf0, /* 00000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xf0, /* 00000000 0000 */ + 0xf0, /* 00000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 92 0x5c '\' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc, /* 000000000000 00 */ + 0xc, /* 000000000000 00 */ + 0xc, /* 000000000000 00 */ + 0xc, /* 000000000000 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 93 0x5d ']' */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 94 0x5e '^' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 95 0x5f '_' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ffc, /* 00 00 */ + 0x3ffc, /* 00 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 96 0x60 '`' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 97 0x61 'a' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 98 0x62 'b' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 99 0x63 'c' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 100 0x64 'd' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 101 0x65 'e' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 102 0x66 'f' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf0, /* 00000000 0000 */ + 0xf0, /* 00000000 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 103 0x67 'g' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 104 0x68 'h' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 105 0x69 'i' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 106 0x6a 'j' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3c00, /* 00 0000000000 */ + 0x3c00, /* 00 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 107 0x6b 'k' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3f00, /* 00 00000000 */ + 0x3f00, /* 00 00000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 108 0x6c 'l' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 109 0x6d 'm' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 110 0x6e 'n' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 111 0x6f 'o' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 112 0x70 'p' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 113 0x71 'q' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 114 0x72 'r' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 115 0x73 's' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 116 0x74 't' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xf0, /* 00000000 0000 */ + 0xf0, /* 00000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 117 0x75 'u' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 118 0x76 'v' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 119 0x77 'w' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 120 0x78 'x' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 121 0x79 'y' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 122 0x7a 'z' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 123 0x7b '{' */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 124 0x7c '|' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 125 0x7d '}' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 126 0x7e '~' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 127 0x7f '^?' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 128 0x80 '\200' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 129 0x81 '\201' */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 130 0x82 '\202' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 131 0x83 '\203' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 132 0x84 '\204' */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 133 0x85 '\205' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 134 0x86 '\206' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 135 0x87 '\207' */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 136 0x88 '\210' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 137 0x89 '\211' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 138 0x8a '\212' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 139 0x8b '\213' */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 140 0x8c '\214' */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 141 0x8d '\215' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 142 0x8e '\216' */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 143 0x8f '\217' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 144 0x90 '\220' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 145 0x91 '\221' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 146 0x92 '\222' */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 147 0x93 '\223' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 148 0x94 '\224' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 149 0x95 '\225' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 150 0x96 '\226' */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 151 0x97 '\227' */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 152 0x98 '\230' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 153 0x99 '\231' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 154 0x9a '\232' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 155 0x9b '\233' */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 156 0x9c '\234' */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 157 0x9d '\235' */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 158 0x9e '\236' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 159 0x9f '\237' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 160 0xa0 '\240' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 161 0xa1 '\241' */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 162 0xa2 '\242' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 163 0xa3 '\243' */ + 0xf00, /* 0000 00000000 */ + 0xf00, /* 0000 00000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3f00, /* 00 00000000 */ + 0x3f00, /* 00 00000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 164 0xa4 '\244' */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 165 0xa5 '\245' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 166 0xa6 '\246' */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 167 0xa7 '\247' */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 168 0xa8 '\250' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3f00, /* 00 00000000 */ + 0x3f00, /* 00 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 169 0xa9 '\251' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3f00, /* 00 00000000 */ + 0x3f00, /* 00 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xf30, /* 0000 00 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3f00, /* 00 00000000 */ + 0x3f00, /* 00 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 170 0xaa '\252' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3fcc, /* 00 00 00 */ + 0x3fcc, /* 00 00 00 */ + 0xcfc, /* 0000 00 00 */ + 0xcfc, /* 0000 00 00 */ + 0xcfc, /* 0000 00 00 */ + 0xcfc, /* 0000 00 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 171 0xab '\253' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 172 0xac '\254' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 173 0xad '\255' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 174 0xae '\256' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3fc0, /* 00 000000 */ + 0x3fc0, /* 00 000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x33f0, /* 00 00 0000 */ + 0x33f0, /* 00 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 175 0xaf '\257' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 176 0xb0 '\260' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 177 0xb1 '\261' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 178 0xb2 '\262' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 179 0xb3 '\263' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3f0, /* 000000 0000 */ + 0x3f0, /* 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 180 0xb4 '\264' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 181 0xb5 '\265' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x3f30, /* 00 00 0000 */ + 0x3f30, /* 00 00 0000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 182 0xb6 '\266' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xf0, /* 00000000 0000 */ + 0xf0, /* 00000000 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 183 0xb7 '\267' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 184 0xb8 '\270' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 185 0xb9 '\271' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 186 0xba '\272' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3c00, /* 00 0000000000 */ + 0x3c00, /* 00 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 187 0xbb '\273' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3f0, /* 000000 0000 */ + 0x3f0, /* 000000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3f0, /* 000000 0000 */ + 0x3f0, /* 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 188 0xbc '\274' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 189 0xbd '\275' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3cf0, /* 00 00 0000 */ + 0x3cf0, /* 00 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 190 0xbe '\276' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x33f0, /* 00 00 0000 */ + 0x33f0, /* 00 00 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 191 0xbf '\277' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x30f0, /* 00 0000 0000 */ + 0x30f0, /* 00 0000 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0x3c30, /* 00 0000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 192 0xc0 '\300' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 193 0xc1 '\301' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 194 0xc2 '\302' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 195 0xc3 '\303' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xf0, /* 00000000 0000 */ + 0xf0, /* 00000000 0000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0xc00, /* 0000 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 196 0xc4 '\304' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3c00, /* 00 0000000000 */ + 0x3c00, /* 00 0000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 197 0xc5 '\305' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3000, /* 00 000000000000 */ + 0x3000, /* 00 000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 198 0xc6 '\306' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 199 0xc7 '\307' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 200 0xc8 '\310' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0xc30, /* 0000 0000 0000 */ + 0x30c0, /* 00 0000 000000 */ + 0x30c0, /* 00 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 201 0xc9 '\311' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 202 0xca '\312' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 203 0xcb '\313' */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 204 0xcc '\314' */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 205 0xcd '\315' */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 206 0xce '\316' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x33c0, /* 00 00 000000 */ + 0x33c0, /* 00 00 000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 207 0xcf '\317' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3330, /* 00 00 00 0000 */ + 0x3330, /* 00 00 00 0000 */ + 0x33f0, /* 00 00 0000 */ + 0x33f0, /* 00 00 0000 */ + 0x3300, /* 00 00 00000000 */ + 0x3300, /* 00 00 00000000 */ + 0xcf0, /* 0000 00 0000 */ + 0xcf0, /* 0000 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 208 0xd0 '\320' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 209 0xd1 '\321' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ffc, /* 00 00 */ + 0x3ffc, /* 00 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 210 0xd2 '\322' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 211 0xd3 '\323' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0x330, /* 000000 00 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 212 0xd4 '\324' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 213 0xd5 '\325' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3c0, /* 000000 000000 */ + 0x3c0, /* 000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0xc0, /* 00000000 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 214 0xd6 '\326' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ff0, /* 00 0000 */ + 0x3ff0, /* 00 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 215 0xd7 '\327' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x300, /* 000000 00000000 */ + 0x300, /* 000000 00000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 216 0xd8 '\330' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xcc0, /* 0000 00 000000 */ + 0xcc0, /* 0000 00 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0x3030, /* 00 000000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x30, /* 0000000000 0000 */ + 0x30, /* 0000000000 0000 */ + 0xfc0, /* 0000 000000 */ + 0xfc0, /* 0000 000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 217 0xd9 '\331' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ffc, /* 00 00 */ + 0x3ffc, /* 00 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ffc, /* 00 00 */ + 0x3ffc, /* 00 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x3ffc, /* 00 00 */ + 0x3ffc, /* 00 00 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 218 0xda '\332' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 219 0xdb '\333' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 220 0xdc '\334' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 221 0xdd '\335' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 222 0xde '\336' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 223 0xdf '\337' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 224 0xe0 '\340' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 225 0xe1 '\341' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 226 0xe2 '\342' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 227 0xe3 '\343' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 228 0xe4 '\344' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 229 0xe5 '\345' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 230 0xe6 '\346' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 231 0xe7 '\347' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 232 0xe8 '\350' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 233 0xe9 '\351' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 234 0xea '\352' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 235 0xeb '\353' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 236 0xec '\354' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 237 0xed '\355' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 238 0xee '\356' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 239 0xef '\357' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 240 0xf0 '\360' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 241 0xf1 '\361' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 242 0xf2 '\362' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 243 0xf3 '\363' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 244 0xf4 '\364' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 245 0xf5 '\365' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 246 0xf6 '\366' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 247 0xf7 '\367' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 248 0xf8 '\370' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 249 0xf9 '\371' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 250 0xfa '\372' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 251 0xfb '\373' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 252 0xfc '\374' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 253 0xfd '\375' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 254 0xfe '\376' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + + /* 255 0xff '\377' */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0xff0, /* 0000 0000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ + 0x0, /* 0000000000000000 */ }; diff --git a/src/zm_box.h b/src/zm_box.h index 8aa341d73..f5fe69a38 100644 --- a/src/zm_box.h +++ b/src/zm_box.h @@ -36,39 +36,39 @@ class Box { private: - Coord lo, hi; - Coord size; + Coord lo, hi; + Coord size; public: - inline Box() - { - } - inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { } - inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { } - inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { } - inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { } + inline Box() + { + } + inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { } + inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { } + inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { } + inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { } - inline const Coord &Lo() const { return( lo ); } - inline int LoX() const { return( lo.X() ); } - inline int LoY() const { return( lo.Y() ); } - inline const Coord &Hi() const { return( hi ); } - inline int HiX() const { return( hi.X() ); } - inline int HiY() const { return( hi.Y() ); } - inline const Coord &Size() const { return( size ); } - inline int Width() const { return( size.X() ); } - inline int Height() const { return( size.Y() ); } - inline int Area() const { return( size.X()*size.Y() ); } + inline const Coord &Lo() const { return( lo ); } + inline int LoX() const { return( lo.X() ); } + inline int LoY() const { return( lo.Y() ); } + inline const Coord &Hi() const { return( hi ); } + inline int HiX() const { return( hi.X() ); } + inline int HiY() const { return( hi.Y() ); } + inline const Coord &Size() const { return( size ); } + inline int Width() const { return( size.X() ); } + inline int Height() const { return( size.Y() ); } + inline int Area() const { return( size.X()*size.Y() ); } - inline const Coord Centre() const - { - int mid_x = int(round(lo.X()+(size.X()/2.0))); - int mid_y = int(round(lo.Y()+(size.Y()/2.0))); - return( Coord( mid_x, mid_y ) ); - } - inline bool Inside( const Coord &coord ) const - { - return( coord.X() >= lo.X() && coord.X() <= hi.X() && coord.Y() >= lo.Y() && coord.Y() <= hi.Y() ); - } + inline const Coord Centre() const + { + int mid_x = int(round(lo.X()+(size.X()/2.0))); + int mid_y = int(round(lo.Y()+(size.Y()/2.0))); + return( Coord( mid_x, mid_y ) ); + } + inline bool Inside( const Coord &coord ) const + { + return( coord.X() >= lo.X() && coord.X() <= hi.X() && coord.Y() >= lo.Y() && coord.Y() <= hi.Y() ); + } }; #endif // ZM_BOX_H diff --git a/src/zm_buffer.cpp b/src/zm_buffer.cpp index d2fb2ef72..b46cb2f15 100644 --- a/src/zm_buffer.cpp +++ b/src/zm_buffer.cpp @@ -25,57 +25,57 @@ unsigned int Buffer::assign( const unsigned char *pStorage, unsigned int pSize ) { - if ( mAllocation < pSize ) - { - delete[] mStorage; - mAllocation = pSize; - mHead = mStorage = new unsigned char[pSize]; - } - mSize = pSize; - memcpy( mStorage, pStorage, mSize ); - mHead = mStorage; - mTail = mHead + mSize; - return( mSize ); + if ( mAllocation < pSize ) + { + delete[] mStorage; + mAllocation = pSize; + mHead = mStorage = new unsigned char[pSize]; + } + mSize = pSize; + memcpy( mStorage, pStorage, mSize ); + mHead = mStorage; + mTail = mHead + mSize; + return( mSize ); } unsigned int Buffer::expand( unsigned int count ) { - int spare = mAllocation - mSize; - int headSpace = mHead - mStorage; - int tailSpace = spare - headSpace; - int width = mTail - mHead; - if ( spare > (int)count ) + int spare = mAllocation - mSize; + int headSpace = mHead - mStorage; + int tailSpace = spare - headSpace; + int width = mTail - mHead; + if ( spare > (int)count ) + { + if ( tailSpace < (int)count ) { - if ( tailSpace < (int)count ) - { - memmove( mStorage, mHead, mSize ); - mHead = mStorage; - mTail = mHead + width; - } + memmove( mStorage, mHead, mSize ); + mHead = mStorage; + mTail = mHead + width; } - else + } + else + { + mAllocation += count; + unsigned char *newStorage = new unsigned char[mAllocation]; + if ( mStorage ) { - mAllocation += count; - unsigned char *newStorage = new unsigned char[mAllocation]; - if ( mStorage ) - { - memcpy( newStorage, mHead, mSize ); - delete[] mStorage; - } - mStorage = newStorage; - mHead = mStorage; - mTail = mHead + width; + memcpy( newStorage, mHead, mSize ); + delete[] mStorage; } - return( mSize ); + mStorage = newStorage; + mHead = mStorage; + mTail = mHead + width; + } + return( mSize ); } int Buffer::read_into( int sd, unsigned int bytes ) { - // Make sure there is enough space - this->expand(bytes); - int bytes_read = read( sd, mTail, bytes ); - if ( bytes_read > 0 ) { - mTail += bytes_read; - mSize += bytes_read; - } - return bytes_read; + // Make sure there is enough space + this->expand(bytes); + int bytes_read = read( sd, mTail, bytes ); + if ( bytes_read > 0 ) { + mTail += bytes_read; + mSize += bytes_read; + } + return bytes_read; } diff --git a/src/zm_buffer.h b/src/zm_buffer.h index 007df4459..620fce1a8 100644 --- a/src/zm_buffer.h +++ b/src/zm_buffer.h @@ -27,183 +27,183 @@ class Buffer { protected: - unsigned char *mStorage; - unsigned int mAllocation; - unsigned int mSize; - unsigned char *mHead; - unsigned char *mTail; + unsigned char *mStorage; + unsigned int mAllocation; + unsigned int mSize; + unsigned char *mHead; + unsigned char *mTail; public: - Buffer() : mStorage( 0 ), mAllocation( 0 ), mSize( 0 ), mHead( 0 ), mTail( 0 ) + Buffer() : mStorage( 0 ), mAllocation( 0 ), mSize( 0 ), mHead( 0 ), mTail( 0 ) + { + } + Buffer( unsigned int pSize ) : mAllocation( pSize ), mSize( 0 ) + { + mHead = mStorage = new unsigned char[mAllocation]; + mTail = mHead; + } + Buffer( const unsigned char *pStorage, unsigned int pSize ) : mAllocation( pSize ), mSize( pSize ) + { + mHead = mStorage = new unsigned char[mSize]; + memcpy( mStorage, pStorage, mSize ); + mTail = mHead + mSize; + } + Buffer( const Buffer &buffer ) : mAllocation( buffer.mSize ), mSize( buffer.mSize ) + { + mHead = mStorage = new unsigned char[mSize]; + memcpy( mStorage, buffer.mHead, mSize ); + mTail = mHead + mSize; + } + ~Buffer() + { + delete[] mStorage; + } + unsigned char *head() const { return( mHead ); } + unsigned char *tail() const { return( mTail ); } + unsigned int size() const { return( mSize ); } + bool empty() const { return( mSize == 0 ); } + unsigned int size( unsigned int pSize ) + { + if ( mSize < pSize ) { + expand( pSize-mSize ); } - Buffer( unsigned int pSize ) : mAllocation( pSize ), mSize( 0 ) - { - mHead = mStorage = new unsigned char[mAllocation]; - mTail = mHead; - } - Buffer( const unsigned char *pStorage, unsigned int pSize ) : mAllocation( pSize ), mSize( pSize ) - { - mHead = mStorage = new unsigned char[mSize]; - memcpy( mStorage, pStorage, mSize ); - mTail = mHead + mSize; - } - Buffer( const Buffer &buffer ) : mAllocation( buffer.mSize ), mSize( buffer.mSize ) - { - mHead = mStorage = new unsigned char[mSize]; - memcpy( mStorage, buffer.mHead, mSize ); - mTail = mHead + mSize; - } - ~Buffer() - { - delete[] mStorage; - } - unsigned char *head() const { return( mHead ); } - unsigned char *tail() const { return( mTail ); } - unsigned int size() const { return( mSize ); } - bool empty() const { return( mSize == 0 ); } - unsigned int size( unsigned int pSize ) - { - if ( mSize < pSize ) - { - expand( pSize-mSize ); - } - return( mSize ); - } - //unsigned int Allocation() const { return( mAllocation ); } + return( mSize ); + } + //unsigned int Allocation() const { return( mAllocation ); } - void clear() + void clear() + { + mSize = 0; + mHead = mTail = mStorage; + } + + unsigned int assign( const unsigned char *pStorage, unsigned int pSize ); + unsigned int assign( const Buffer &buffer ) + { + return( assign( buffer.mHead, buffer.mSize ) ); + } + + // Trim from the front of the buffer + unsigned int consume( unsigned int count ) + { + if ( count > mSize ) { - mSize = 0; + Warning( "Attempt to consume %d bytes of buffer, size is only %d bytes", count, mSize ); + count = mSize; + } + mHead += count; + mSize -= count; + tidy( 0 ); + return( count ); + } + // Trim from the end of the buffer + unsigned int shrink( unsigned int count ) + { + if ( count > mSize ) + { + Warning( "Attempt to shrink buffer by %d bytes, size is only %d bytes", count, mSize ); + count = mSize; + } + mSize -= count; + if ( mTail > (mHead + mSize) ) + mTail = mHead + mSize; + tidy( 0 ); + return( count ); + } + // Add to the end of the buffer + unsigned int expand( unsigned int count ); + + // Return pointer to the first pSize bytes and advance the head + unsigned char *extract( unsigned int pSize ) + { + if ( pSize > mSize ) + { + Warning( "Attempt to extract %d bytes of buffer, size is only %d bytes", pSize, mSize ); + pSize = mSize; + } + unsigned char *oldHead = mHead; + mHead += pSize; + mSize -= pSize; + tidy( 0 ); + return( oldHead ); + } + // Add bytes to the end of the buffer + unsigned int append( const unsigned char *pStorage, unsigned int pSize ) + { + expand( pSize ); + memcpy( mTail, pStorage, pSize ); + mTail += pSize; + mSize += pSize; + return( mSize ); + } + unsigned int append( const char *pStorage, unsigned int pSize ) + { + return( append( (const unsigned char *)pStorage, pSize ) ); + } + unsigned int append( const Buffer &buffer ) + { + return( append( buffer.mHead, buffer.mSize ) ); + } + void tidy( bool level=0 ) + { + if ( mHead != mStorage ) + { + if ( mSize == 0 ) mHead = mTail = mStorage; - } - - unsigned int assign( const unsigned char *pStorage, unsigned int pSize ); - unsigned int assign( const Buffer &buffer ) - { - return( assign( buffer.mHead, buffer.mSize ) ); - } - - // Trim from the front of the buffer - unsigned int consume( unsigned int count ) - { - if ( count > mSize ) + else if ( level ) + { + if ( (mHead-mStorage) > mSize ) { - Warning( "Attempt to consume %d bytes of buffer, size is only %d bytes", count, mSize ); - count = mSize; + memcpy( mStorage, mHead, mSize ); + mHead = mStorage; + mTail = mHead + mSize; } - mHead += count; - mSize -= count; - tidy( 0 ); - return( count ); + } } - // Trim from the end of the buffer - unsigned int shrink( unsigned int count ) - { - if ( count > mSize ) - { - Warning( "Attempt to shrink buffer by %d bytes, size is only %d bytes", count, mSize ); - count = mSize; - } - mSize -= count; - if ( mTail > (mHead + mSize) ) - mTail = mHead + mSize; - tidy( 0 ); - return( count ); - } - // Add to the end of the buffer - unsigned int expand( unsigned int count ); + } - // Return pointer to the first pSize bytes and advance the head - unsigned char *extract( unsigned int pSize ) - { - if ( pSize > mSize ) - { - Warning( "Attempt to extract %d bytes of buffer, size is only %d bytes", pSize, mSize ); - pSize = mSize; - } - unsigned char *oldHead = mHead; - mHead += pSize; - mSize -= pSize; - tidy( 0 ); - return( oldHead ); - } - // Add bytes to the end of the buffer - unsigned int append( const unsigned char *pStorage, unsigned int pSize ) - { - expand( pSize ); - memcpy( mTail, pStorage, pSize ); - mTail += pSize; - mSize += pSize; - return( mSize ); - } - unsigned int append( const char *pStorage, unsigned int pSize ) - { - return( append( (const unsigned char *)pStorage, pSize ) ); - } - unsigned int append( const Buffer &buffer ) - { - return( append( buffer.mHead, buffer.mSize ) ); - } - void tidy( bool level=0 ) - { - if ( mHead != mStorage ) - { - if ( mSize == 0 ) - mHead = mTail = mStorage; - else if ( level ) - { - if ( (mHead-mStorage) > mSize ) - { - memcpy( mStorage, mHead, mSize ); - mHead = mStorage; - mTail = mHead + mSize; - } - } - } - } - - Buffer &operator=( const Buffer &buffer ) - { - assign( buffer ); - return( *this ); - } - Buffer &operator+=( const Buffer &buffer ) - { - append( buffer ); - return( *this ); - } - Buffer &operator+=( unsigned int count ) - { - expand( count ); - return( *this ); - } - Buffer &operator-=( unsigned int count ) - { - consume( count ); - return( *this ); - } - operator unsigned char *() const - { - return( mHead ); - } - operator char *() const - { - return( (char *)mHead ); - } - unsigned char *operator+(int offset) const - { - return( (unsigned char *)(mHead+offset) ); - } - unsigned char operator[](int index) const - { - return( *(mHead+index) ); - } - operator int () const - { - return( (int)mSize ); - } - int read_into( int sd, unsigned int bytes ); + Buffer &operator=( const Buffer &buffer ) + { + assign( buffer ); + return( *this ); + } + Buffer &operator+=( const Buffer &buffer ) + { + append( buffer ); + return( *this ); + } + Buffer &operator+=( unsigned int count ) + { + expand( count ); + return( *this ); + } + Buffer &operator-=( unsigned int count ) + { + consume( count ); + return( *this ); + } + operator unsigned char *() const + { + return( mHead ); + } + operator char *() const + { + return( (char *)mHead ); + } + unsigned char *operator+(int offset) const + { + return( (unsigned char *)(mHead+offset) ); + } + unsigned char operator[](int index) const + { + return( *(mHead+index) ); + } + operator int () const + { + return( (int)mSize ); + } + int read_into( int sd, unsigned int bytes ); }; #endif // ZM_BUFFER_H diff --git a/src/zm_camera.cpp b/src/zm_camera.cpp index 18950d341..bbf2edcb6 100644 --- a/src/zm_camera.cpp +++ b/src/zm_camera.cpp @@ -21,29 +21,29 @@ #include "zm_camera.h" Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - id( p_id ), - type( p_type ), - width( p_width), - height( p_height ), - colours( p_colours ), - subpixelorder( p_subpixelorder ), - brightness( p_brightness ), - hue( p_hue ), - colour( p_colour ), - contrast( p_contrast ), - capture( p_capture ) + id( p_id ), + type( p_type ), + width( p_width), + height( p_height ), + colours( p_colours ), + subpixelorder( p_subpixelorder ), + brightness( p_brightness ), + hue( p_hue ), + colour( p_colour ), + contrast( p_contrast ), + capture( p_capture ) { - pixels = width * height; - imagesize = pixels * colours; - - Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture); - - /* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */ - if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 16) != 0) { - Fatal("Image size is not multiples of 16"); - } else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 16) != 0 || (imagesize % 12) != 0)) { - Fatal("Image size is not multiples of 12 and 16"); - } + pixels = width * height; + imagesize = pixels * colours; + + Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture); + + /* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */ + if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 16) != 0) { + Fatal("Image size is not multiples of 16"); + } else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 16) != 0 || (imagesize % 12) != 0)) { + Fatal("Image size is not multiples of 12 and 16"); + } } Camera::~Camera() diff --git a/src/zm_camera.h b/src/zm_camera.h index bddb66fc8..ba8224c09 100644 --- a/src/zm_camera.h +++ b/src/zm_camera.h @@ -32,52 +32,52 @@ class Camera { protected: - typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType; + typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType; - int id; - SourceType type; - unsigned int width; - unsigned int height; - unsigned int colours; - unsigned int subpixelorder; - unsigned int pixels; - unsigned int imagesize; - int brightness; - int hue; - int colour; - int contrast; - bool capture; + int id; + SourceType type; + unsigned int width; + unsigned int height; + unsigned int colours; + unsigned int subpixelorder; + unsigned int pixels; + unsigned int imagesize; + int brightness; + int hue; + int colour; + int contrast; + bool capture; public: - Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - virtual ~Camera(); + Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + virtual ~Camera(); - int getId() const { return( id ); } - SourceType Type() const { return( type ); } - bool IsLocal() const { return( type == LOCAL_SRC ); } - bool IsRemote() const { return( type == REMOTE_SRC ); } - bool IsFile() const { return( type == FILE_SRC ); } - bool IsFfmpeg() const { return( type == FFMPEG_SRC ); } - bool IsLibvlc() const { return( type == LIBVLC_SRC ); } - bool IscURL() const { return( type == CURL_SRC ); } - unsigned int Width() const { return( width ); } - unsigned int Height() const { return( height ); } - unsigned int Colours() const { return( colours ); } - unsigned int SubpixelOrder() const { return( subpixelorder ); } - unsigned int Pixels() const { return( pixels ); } - unsigned int ImageSize() const { return( imagesize ); } + int getId() const { return( id ); } + SourceType Type() const { return( type ); } + bool IsLocal() const { return( type == LOCAL_SRC ); } + bool IsRemote() const { return( type == REMOTE_SRC ); } + bool IsFile() const { return( type == FILE_SRC ); } + bool IsFfmpeg() const { return( type == FFMPEG_SRC ); } + bool IsLibvlc() const { return( type == LIBVLC_SRC ); } + bool IscURL() const { return( type == CURL_SRC ); } + unsigned int Width() const { return( width ); } + unsigned int Height() const { return( height ); } + unsigned int Colours() const { return( colours ); } + unsigned int SubpixelOrder() const { return( subpixelorder ); } + unsigned int Pixels() const { return( pixels ); } + unsigned int ImageSize() const { return( imagesize ); } - virtual int Brightness( int/*p_brightness*/=-1 ) { return( -1 ); } - virtual int Hue( int/*p_hue*/=-1 ) { return( -1 ); } - virtual int Colour( int/*p_colour*/=-1 ) { return( -1 ); } - virtual int Contrast( int/*p_contrast*/=-1 ) { return( -1 ); } + virtual int Brightness( int/*p_brightness*/=-1 ) { return( -1 ); } + virtual int Hue( int/*p_hue*/=-1 ) { return( -1 ); } + virtual int Colour( int/*p_colour*/=-1 ) { return( -1 ); } + virtual int Contrast( int/*p_contrast*/=-1 ) { return( -1 ); } - bool CanCapture() const { return( capture ); } - - virtual int PrimeCapture() { return( 0 ); } - virtual int PreCapture()=0; - virtual int Capture( Image &image )=0; - virtual int PostCapture()=0; + bool CanCapture() const { return( capture ); } + + virtual int PrimeCapture() { return( 0 ); } + virtual int PreCapture()=0; + virtual int Capture( Image &image )=0; + virtual int PostCapture()=0; }; #endif // ZM_CAMERA_H diff --git a/src/zm_comms.cpp b/src/zm_comms.cpp index a109019bd..1fd224b18 100644 --- a/src/zm_comms.cpp +++ b/src/zm_comms.cpp @@ -42,89 +42,89 @@ int CommsBase::readV( int iovcnt, /* const void *, int, */ ... ) { - va_list arg_ptr; - //struct iovec iov[iovcnt]; - struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt ); + va_list arg_ptr; + //struct iovec iov[iovcnt]; + struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt ); - va_start( arg_ptr, iovcnt ); - for ( int i = 0; i < iovcnt; i++ ) - { - iov[i].iov_base = va_arg( arg_ptr, void * ); - iov[i].iov_len = va_arg( arg_ptr, int ); - } - va_end( arg_ptr ); + va_start( arg_ptr, iovcnt ); + for ( int i = 0; i < iovcnt; i++ ) + { + iov[i].iov_base = va_arg( arg_ptr, void * ); + iov[i].iov_len = va_arg( arg_ptr, int ); + } + va_end( arg_ptr ); - int nBytes = ::readv( mRd, iov, iovcnt ); - if ( nBytes < 0 ) - Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) ); - return( nBytes ); + int nBytes = ::readv( mRd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) ); + return( nBytes ); } int CommsBase::writeV( int iovcnt, /* const void *, int, */ ... ) { - va_list arg_ptr; - //struct iovec iov[iovcnt]; - struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt ); + va_list arg_ptr; + //struct iovec iov[iovcnt]; + struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt ); - va_start( arg_ptr, iovcnt ); - for ( int i = 0; i < iovcnt; i++ ) - { - iov[i].iov_base = va_arg( arg_ptr, void * ); - iov[i].iov_len = va_arg( arg_ptr, int ); - } - va_end( arg_ptr ); + va_start( arg_ptr, iovcnt ); + for ( int i = 0; i < iovcnt; i++ ) + { + iov[i].iov_base = va_arg( arg_ptr, void * ); + iov[i].iov_len = va_arg( arg_ptr, int ); + } + va_end( arg_ptr ); - ssize_t nBytes = ::writev( mWd, iov, iovcnt ); - if ( nBytes < 0 ) - Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) ); - return( nBytes ); + ssize_t nBytes = ::writev( mWd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) ); + return( nBytes ); } bool Pipe::open() { - if ( ::pipe( mFd ) < 0 ) - { - Error( "pipe(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } + if ( ::pipe( mFd ) < 0 ) + { + Error( "pipe(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } - return( true ); + return( true ); } bool Pipe::close() { - if ( mFd[0] > -1 ) ::close( mFd[0] ); - mFd[0] = -1; - if ( mFd[1] > -1 ) ::close( mFd[1] ); - mFd[1] = -1; - return( true ); + if ( mFd[0] > -1 ) ::close( mFd[0] ); + mFd[0] = -1; + if ( mFd[1] > -1 ) ::close( mFd[1] ); + mFd[1] = -1; + return( true ); } bool Pipe::setBlocking( bool blocking ) { - int flags; + int flags; - /* Now set it for non-blocking I/O */ - if ( (flags = fcntl( mFd[1], F_GETFL )) < 0 ) - { - Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - if ( blocking ) - { - flags &= ~O_NONBLOCK; - } - else - { - flags |= O_NONBLOCK; - } - if ( fcntl( mFd[1], F_SETFL, flags ) < 0 ) - { - Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } + /* Now set it for non-blocking I/O */ + if ( (flags = fcntl( mFd[1], F_GETFL )) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + if ( blocking ) + { + flags &= ~O_NONBLOCK; + } + else + { + flags |= O_NONBLOCK; + } + if ( fcntl( mFd[1], F_SETFL, flags ) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } - return( true ); + return( true ); } SockAddr::SockAddr( const struct sockaddr *addr ) : mAddr( addr ) @@ -133,33 +133,33 @@ SockAddr::SockAddr( const struct sockaddr *addr ) : mAddr( addr ) SockAddr *SockAddr::newSockAddr( const struct sockaddr &addr, socklen_t len ) { - if ( addr.sa_family == AF_INET && len == SockAddrInet::addrSize() ) - { - return( new SockAddrInet( (const struct sockaddr_in *)&addr ) ); - } - else if ( addr.sa_family == AF_UNIX && len == SockAddrUnix::addrSize() ) - { - return( new SockAddrUnix( (const struct sockaddr_un *)&addr ) ); - } - Error( "Unable to create new SockAddr from addr family %d with size %d", addr.sa_family, len ); - return( 0 ); + if ( addr.sa_family == AF_INET && len == SockAddrInet::addrSize() ) + { + return( new SockAddrInet( (const struct sockaddr_in *)&addr ) ); + } + else if ( addr.sa_family == AF_UNIX && len == SockAddrUnix::addrSize() ) + { + return( new SockAddrUnix( (const struct sockaddr_un *)&addr ) ); + } + Error( "Unable to create new SockAddr from addr family %d with size %d", addr.sa_family, len ); + return( 0 ); } SockAddr *SockAddr::newSockAddr( const SockAddr *addr ) { - if ( !addr ) - return( 0 ); - - if ( addr->getDomain() == AF_INET ) - { - return( new SockAddrInet( *(SockAddrInet *)addr ) ); - } - else if ( addr->getDomain() == AF_UNIX ) - { - return( new SockAddrUnix( *(SockAddrUnix *)addr ) ); - } - Error( "Unable to create new SockAddr from addr family %d", addr->getDomain() ); + if ( !addr ) return( 0 ); + + if ( addr->getDomain() == AF_INET ) + { + return( new SockAddrInet( *(SockAddrInet *)addr ) ); + } + else if ( addr->getDomain() == AF_UNIX ) + { + return( new SockAddrUnix( *(SockAddrUnix *)addr ) ); + } + Error( "Unable to create new SockAddr from addr family %d", addr->getDomain() ); + return( 0 ); } SockAddrInet::SockAddrInet() : SockAddr( (struct sockaddr *)&mAddrIn ) @@ -168,73 +168,73 @@ SockAddrInet::SockAddrInet() : SockAddr( (struct sockaddr *)&mAddrIn ) bool SockAddrInet::resolve( const char *host, const char *serv, const char *proto ) { - memset( &mAddrIn, 0, sizeof(mAddrIn) ); + memset( &mAddrIn, 0, sizeof(mAddrIn) ); - struct hostent *hostent=0; - if ( !(hostent = ::gethostbyname( host ) ) ) - { - Error( "gethostbyname( %s ), h_errno = %d", host, h_errno ); - return( false ); - } + struct hostent *hostent=0; + if ( !(hostent = ::gethostbyname( host ) ) ) + { + Error( "gethostbyname( %s ), h_errno = %d", host, h_errno ); + return( false ); + } - struct servent *servent=0; - if ( !(servent = ::getservbyname( serv, proto ) ) ) - { - Error( "getservbyname( %s ), errno = %d, error = %s", serv, errno, strerror(errno) ); - return( false ); - } + struct servent *servent=0; + if ( !(servent = ::getservbyname( serv, proto ) ) ) + { + Error( "getservbyname( %s ), errno = %d, error = %s", serv, errno, strerror(errno) ); + return( false ); + } - mAddrIn.sin_port = servent->s_port; - mAddrIn.sin_family = AF_INET; - mAddrIn.sin_addr.s_addr = ((struct in_addr *)(hostent->h_addr))->s_addr; + mAddrIn.sin_port = servent->s_port; + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = ((struct in_addr *)(hostent->h_addr))->s_addr; - return( true ); + return( true ); } bool SockAddrInet::resolve( const char *host, int port, const char *proto ) { - memset( &mAddrIn, 0, sizeof(mAddrIn) ); + memset( &mAddrIn, 0, sizeof(mAddrIn) ); - struct hostent *hostent=0; - if ( !(hostent = ::gethostbyname( host ) ) ) - { - Error( "gethostbyname( %s ), h_errno = %d", host, h_errno ); - return( false ); - } + struct hostent *hostent=0; + if ( !(hostent = ::gethostbyname( host ) ) ) + { + Error( "gethostbyname( %s ), h_errno = %d", host, h_errno ); + return( false ); + } - mAddrIn.sin_port = htons(port); - mAddrIn.sin_family = AF_INET; - mAddrIn.sin_addr.s_addr = ((struct in_addr *)(hostent->h_addr))->s_addr; - return( true ); + mAddrIn.sin_port = htons(port); + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = ((struct in_addr *)(hostent->h_addr))->s_addr; + return( true ); } bool SockAddrInet::resolve( const char *serv, const char *proto ) { - memset( &mAddrIn, 0, sizeof(mAddrIn) ); + memset( &mAddrIn, 0, sizeof(mAddrIn) ); - struct servent *servent=0; - if ( !(servent = ::getservbyname( serv, proto ) ) ) - { - Error( "getservbyname( %s ), errno = %d, error = %s", serv, errno, strerror(errno) ); - return( false ); - } + struct servent *servent=0; + if ( !(servent = ::getservbyname( serv, proto ) ) ) + { + Error( "getservbyname( %s ), errno = %d, error = %s", serv, errno, strerror(errno) ); + return( false ); + } - mAddrIn.sin_port = servent->s_port; - mAddrIn.sin_family = AF_INET; - mAddrIn.sin_addr.s_addr = INADDR_ANY; + mAddrIn.sin_port = servent->s_port; + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = INADDR_ANY; - return( true ); + return( true ); } bool SockAddrInet::resolve( int port, const char *proto ) { - memset( &mAddrIn, 0, sizeof(mAddrIn) ); + memset( &mAddrIn, 0, sizeof(mAddrIn) ); - mAddrIn.sin_port = htons(port); - mAddrIn.sin_family = AF_INET; - mAddrIn.sin_addr.s_addr = INADDR_ANY; + mAddrIn.sin_port = htons(port); + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = INADDR_ANY; - return( true ); + return( true ); } SockAddrUnix::SockAddrUnix() : SockAddr( (struct sockaddr *)&mAddrUn ) @@ -243,313 +243,313 @@ SockAddrUnix::SockAddrUnix() : SockAddr( (struct sockaddr *)&mAddrUn ) bool SockAddrUnix::resolve( const char *path, const char *proto ) { - memset( &mAddrUn, 0, sizeof(mAddrUn) ); + memset( &mAddrUn, 0, sizeof(mAddrUn) ); - strncpy( mAddrUn.sun_path, path, sizeof(mAddrUn.sun_path) ); - mAddrUn.sun_family = AF_UNIX; + strncpy( mAddrUn.sun_path, path, sizeof(mAddrUn.sun_path) ); + mAddrUn.sun_family = AF_UNIX; - return( true ); + return( true ); } bool Socket::socket() { - if ( mSd >= 0 ) - return( true ); + if ( mSd >= 0 ) + return( true ); - if ( (mSd = ::socket( getDomain(), getType(), 0 ) ) < 0 ) - { - Error( "socket(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } + if ( (mSd = ::socket( getDomain(), getType(), 0 ) ) < 0 ) + { + Error( "socket(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } - int val = 1; + int val = 1; - (void)::setsockopt( mSd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val) ); - (void)::setsockopt( mSd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val) ); + (void)::setsockopt( mSd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val) ); + (void)::setsockopt( mSd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val) ); - mState = DISCONNECTED; + mState = DISCONNECTED; - return( true ); + return( true ); } bool Socket::connect() { - if ( !socket() ) - return( false ); + if ( !socket() ) + return( false ); - if ( ::connect( mSd, mRemoteAddr->getAddr(), getAddrSize() ) == -1 ) - { - Error( "connect(), errno = %d, error = %s", errno, strerror(errno) ); - close(); - return( false ); - } + if ( ::connect( mSd, mRemoteAddr->getAddr(), getAddrSize() ) == -1 ) + { + Error( "connect(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } - mState = CONNECTED; + mState = CONNECTED; - return( true ); + return( true ); } bool Socket::bind() { - if ( !socket() ) - return( false ); + if ( !socket() ) + return( false ); - if ( ::bind( mSd, mLocalAddr->getAddr(), getAddrSize() ) == -1 ) - { - Error( "bind(), errno = %d, error = %s", errno, strerror(errno) ); - close(); - return( false ); - } - return( true ); + if ( ::bind( mSd, mLocalAddr->getAddr(), getAddrSize() ) == -1 ) + { + Error( "bind(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } + return( true ); } bool Socket::listen() { - if ( ::listen( mSd, SOMAXCONN ) == -1 ) - { - Error( "listen(), errno = %d, error = %s", errno, strerror(errno) ); - close(); - return( false ); - } + if ( ::listen( mSd, SOMAXCONN ) == -1 ) + { + Error( "listen(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } - mState = LISTENING; + mState = LISTENING; - return( true ); + return( true ); } bool Socket::accept() { - struct sockaddr *rem_addr = mLocalAddr->getTempAddr(); - socklen_t rem_addr_size = getAddrSize(); + struct sockaddr *rem_addr = mLocalAddr->getTempAddr(); + socklen_t rem_addr_size = getAddrSize(); - int newSd = -1; - if ( (newSd = ::accept( mSd, rem_addr, &rem_addr_size )) == -1 ) - { - Error( "accept(), errno = %d, error = %s", errno, strerror(errno) ); - close(); - return( false ); - } + int newSd = -1; + if ( (newSd = ::accept( mSd, rem_addr, &rem_addr_size )) == -1 ) + { + Error( "accept(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } - ::close( mSd ); - mSd = newSd; + ::close( mSd ); + mSd = newSd; - mState = CONNECTED; + mState = CONNECTED; - return( true ); + return( true ); } bool Socket::accept( int &newSd ) { - struct sockaddr *rem_addr = mLocalAddr->getTempAddr(); - socklen_t rem_addr_size = getAddrSize(); + struct sockaddr *rem_addr = mLocalAddr->getTempAddr(); + socklen_t rem_addr_size = getAddrSize(); - newSd = -1; - if ( (newSd = ::accept( mSd, rem_addr, &rem_addr_size )) == -1 ) - { - Error( "accept(), errno = %d, error = %s", errno, strerror(errno) ); - close(); - return( false ); - } + newSd = -1; + if ( (newSd = ::accept( mSd, rem_addr, &rem_addr_size )) == -1 ) + { + Error( "accept(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } - return( true ); + return( true ); } bool Socket::close() { - if ( mSd > -1 ) ::close( mSd ); - mSd = -1; - mState = CLOSED; - return( true ); + if ( mSd > -1 ) ::close( mSd ); + mSd = -1; + mState = CLOSED; + return( true ); } int Socket::bytesToRead() const { - int bytes_to_read = 0; + int bytes_to_read = 0; - if ( ioctl( mSd, FIONREAD, &bytes_to_read ) < 0 ) - { - Error( "ioctl(), errno = %d, error = %s", errno, strerror(errno) ); - return( -1 ); - } - return( bytes_to_read ); + if ( ioctl( mSd, FIONREAD, &bytes_to_read ) < 0 ) + { + Error( "ioctl(), errno = %d, error = %s", errno, strerror(errno) ); + return( -1 ); + } + return( bytes_to_read ); } bool Socket::getBlocking( bool &blocking ) { - int flags; + int flags; - if ( (flags = fcntl( mSd, F_GETFL )) < 0 ) - { - Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - blocking = (flags & O_NONBLOCK); - return( true ); + if ( (flags = fcntl( mSd, F_GETFL )) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + blocking = (flags & O_NONBLOCK); + return( true ); } bool Socket::setBlocking( bool blocking ) { #if 0 - // ioctl is apparently not recommended - int ioctl_arg = !blocking; - if ( ioctl( mSd, FIONBIO, &ioctl_arg ) < 0 ) - { - Error( "ioctl(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - return( true ); + // ioctl is apparently not recommended + int ioctl_arg = !blocking; + if ( ioctl( mSd, FIONBIO, &ioctl_arg ) < 0 ) + { + Error( "ioctl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); #endif - int flags; + int flags; - /* Now set it for non-blocking I/O */ - if ( (flags = fcntl( mSd, F_GETFL )) < 0 ) - { - Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - if ( blocking ) - { - flags &= ~O_NONBLOCK; - } - else - { - flags |= O_NONBLOCK; - } - if ( fcntl( mSd, F_SETFL, flags ) < 0 ) - { - Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } + /* Now set it for non-blocking I/O */ + if ( (flags = fcntl( mSd, F_GETFL )) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + if ( blocking ) + { + flags &= ~O_NONBLOCK; + } + else + { + flags |= O_NONBLOCK; + } + if ( fcntl( mSd, F_SETFL, flags ) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } - return( true ); + return( true ); } bool Socket::getSendBufferSize( int &buffersize ) const { - socklen_t optlen = sizeof(buffersize); - if ( getsockopt( mSd, SOL_SOCKET, SO_SNDBUF, &buffersize, &optlen ) < 0 ) - { - Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( -1 ); - } - return( buffersize ); + socklen_t optlen = sizeof(buffersize); + if ( getsockopt( mSd, SOL_SOCKET, SO_SNDBUF, &buffersize, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( -1 ); + } + return( buffersize ); } bool Socket::getRecvBufferSize( int &buffersize ) const { - socklen_t optlen = sizeof(buffersize); - if ( getsockopt( mSd, SOL_SOCKET, SO_RCVBUF, &buffersize, &optlen ) < 0 ) - { - Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( -1 ); - } - return( buffersize ); + socklen_t optlen = sizeof(buffersize); + if ( getsockopt( mSd, SOL_SOCKET, SO_RCVBUF, &buffersize, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( -1 ); + } + return( buffersize ); } bool Socket::setSendBufferSize( int buffersize ) { - if ( setsockopt( mSd, SOL_SOCKET, SO_SNDBUF, (char *)&buffersize, sizeof(buffersize)) < 0 ) - { - Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - return( true ); + if ( setsockopt( mSd, SOL_SOCKET, SO_SNDBUF, (char *)&buffersize, sizeof(buffersize)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); } bool Socket::setRecvBufferSize( int buffersize ) { - if ( setsockopt( mSd, SOL_SOCKET, SO_RCVBUF, (char *)&buffersize, sizeof(buffersize)) < 0 ) - { - Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - return( true ); + if ( setsockopt( mSd, SOL_SOCKET, SO_RCVBUF, (char *)&buffersize, sizeof(buffersize)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); } bool Socket::getRouting( bool &route ) const { - int dontRoute; - socklen_t optlen = sizeof(dontRoute); - if ( getsockopt( mSd, SOL_SOCKET, SO_DONTROUTE, &dontRoute, &optlen ) < 0 ) - { - Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - route = !dontRoute; - return( true ); + int dontRoute; + socklen_t optlen = sizeof(dontRoute); + if ( getsockopt( mSd, SOL_SOCKET, SO_DONTROUTE, &dontRoute, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + route = !dontRoute; + return( true ); } bool Socket::setRouting( bool route ) { - int dontRoute = !route; - if ( setsockopt( mSd, SOL_SOCKET, SO_DONTROUTE, (char *)&dontRoute, sizeof(dontRoute)) < 0 ) - { - Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - return( true ); + int dontRoute = !route; + if ( setsockopt( mSd, SOL_SOCKET, SO_DONTROUTE, (char *)&dontRoute, sizeof(dontRoute)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); } bool Socket::getNoDelay( bool &nodelay ) const { - int int_nodelay; - socklen_t optlen = sizeof(int_nodelay); - if ( getsockopt( mSd, IPPROTO_TCP, TCP_NODELAY, &int_nodelay, &optlen ) < 0 ) - { - Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - nodelay = int_nodelay; - return( true ); + int int_nodelay; + socklen_t optlen = sizeof(int_nodelay); + if ( getsockopt( mSd, IPPROTO_TCP, TCP_NODELAY, &int_nodelay, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + nodelay = int_nodelay; + return( true ); } bool Socket::setNoDelay( bool nodelay ) { - int int_nodelay = nodelay; + int int_nodelay = nodelay; - if ( setsockopt( mSd, IPPROTO_TCP, TCP_NODELAY, (char *)&int_nodelay, sizeof(int_nodelay)) < 0 ) - { - Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); - return( false ); - } - return( true ); + if ( setsockopt( mSd, IPPROTO_TCP, TCP_NODELAY, (char *)&int_nodelay, sizeof(int_nodelay)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); } bool TcpInetServer::listen() { - return( Socket::listen() ); + return( Socket::listen() ); } bool TcpInetServer::accept() { - return( Socket::accept() ); + return( Socket::accept() ); } bool TcpInetServer::accept( TcpInetSocket *&newSocket ) { - int newSd = -1; - newSocket = 0; + int newSd = -1; + newSocket = 0; - if ( !Socket::accept( newSd ) ) - return( false ); + if ( !Socket::accept( newSd ) ) + return( false ); - newSocket = new TcpInetSocket( *this, newSd ); + newSocket = new TcpInetSocket( *this, newSd ); - return( true ); + return( true ); } bool TcpUnixServer::accept( TcpUnixSocket *&newSocket ) { - int newSd = -1; - newSocket = 0; + int newSd = -1; + newSocket = 0; - if ( !Socket::accept( newSd ) ) - return( false ); + if ( !Socket::accept( newSd ) ) + return( false ); - newSocket = new TcpUnixSocket( *this, newSd ); + newSocket = new TcpUnixSocket( *this, newSd ); - return( true ); + return( true ); } Select::Select() : mHasTimeout( false ), mMaxFd( -1 ) @@ -558,160 +558,160 @@ Select::Select() : mHasTimeout( false ), mMaxFd( -1 ) Select::Select( struct timeval timeout ) : mMaxFd( -1 ) { - setTimeout( timeout ); + setTimeout( timeout ); } Select::Select( int timeout ) : mMaxFd( -1 ) { - setTimeout( timeout ); + setTimeout( timeout ); } Select::Select( double timeout ) : mMaxFd( -1 ) { - setTimeout( timeout ); + setTimeout( timeout ); } void Select::setTimeout( int timeout ) { - mTimeout.tv_sec = timeout; - mTimeout.tv_usec = 0; - mHasTimeout = true; + mTimeout.tv_sec = timeout; + mTimeout.tv_usec = 0; + mHasTimeout = true; } void Select::setTimeout( double timeout ) { - mTimeout.tv_sec = int(timeout); - mTimeout.tv_usec = suseconds_t((timeout-mTimeout.tv_sec)*1000000.0); - mHasTimeout = true; + mTimeout.tv_sec = int(timeout); + mTimeout.tv_usec = suseconds_t((timeout-mTimeout.tv_sec)*1000000.0); + mHasTimeout = true; } void Select::setTimeout( struct timeval timeout ) { - mTimeout = timeout; - mHasTimeout = true; + mTimeout = timeout; + mHasTimeout = true; } void Select::clearTimeout() { - mHasTimeout = false; + mHasTimeout = false; } void Select::calcMaxFd() { - mMaxFd = -1; - for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) - if ( (*iter)->getMaxDesc() > mMaxFd ) - mMaxFd = (*iter)->getMaxDesc(); - for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) - if ( (*iter)->getMaxDesc() > mMaxFd ) - mMaxFd = (*iter)->getMaxDesc(); + mMaxFd = -1; + for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) + if ( (*iter)->getMaxDesc() > mMaxFd ) + mMaxFd = (*iter)->getMaxDesc(); + for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) + if ( (*iter)->getMaxDesc() > mMaxFd ) + mMaxFd = (*iter)->getMaxDesc(); } bool Select::addReader( CommsBase *comms ) { - if ( !comms->isOpen() ) - { - Error( "Unable to add closed reader" ); - return( false ); - } - std::pair result = mReaders.insert( comms ); - if ( result.second ) - if ( comms->getMaxDesc() > mMaxFd ) - mMaxFd = comms->getMaxDesc(); - return( result.second ); + if ( !comms->isOpen() ) + { + Error( "Unable to add closed reader" ); + return( false ); + } + std::pair result = mReaders.insert( comms ); + if ( result.second ) + if ( comms->getMaxDesc() > mMaxFd ) + mMaxFd = comms->getMaxDesc(); + return( result.second ); } bool Select::deleteReader( CommsBase *comms ) { - if ( !comms->isOpen() ) - { - Error( "Unable to add closed reader" ); - return( false ); - } - if ( mReaders.erase( comms ) ) - { - calcMaxFd(); - return( true ); - } + if ( !comms->isOpen() ) + { + Error( "Unable to add closed reader" ); return( false ); + } + if ( mReaders.erase( comms ) ) + { + calcMaxFd(); + return( true ); + } + return( false ); } void Select::clearReaders() { - mReaders.clear(); - mMaxFd = -1; + mReaders.clear(); + mMaxFd = -1; } bool Select::addWriter( CommsBase *comms ) { - std::pair result = mWriters.insert( comms ); - if ( result.second ) - if ( comms->getMaxDesc() > mMaxFd ) - mMaxFd = comms->getMaxDesc(); - return( result.second ); + std::pair result = mWriters.insert( comms ); + if ( result.second ) + if ( comms->getMaxDesc() > mMaxFd ) + mMaxFd = comms->getMaxDesc(); + return( result.second ); } bool Select::deleteWriter( CommsBase *comms ) { - if ( mWriters.erase( comms ) ) - { - calcMaxFd(); - return( true ); - } - return( false ); + if ( mWriters.erase( comms ) ) + { + calcMaxFd(); + return( true ); + } + return( false ); } void Select::clearWriters() { - mWriters.clear(); - mMaxFd = -1; + mWriters.clear(); + mMaxFd = -1; } int Select::wait() { - struct timeval tempTimeout = mTimeout; - struct timeval *selectTimeout = mHasTimeout?&tempTimeout:NULL; + struct timeval tempTimeout = mTimeout; + struct timeval *selectTimeout = mHasTimeout?&tempTimeout:NULL; - fd_set rfds; - fd_set wfds; + fd_set rfds; + fd_set wfds; - mReadable.clear(); - FD_ZERO(&rfds); + mReadable.clear(); + FD_ZERO(&rfds); + for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) + FD_SET((*iter)->getReadDesc(),&rfds); + + mWriteable.clear(); + FD_ZERO(&wfds); + for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) + FD_SET((*iter)->getWriteDesc(),&wfds); + + int nFound = select( mMaxFd+1, &rfds, &wfds, NULL, selectTimeout ); + if( nFound == 0 ) + { + Debug( 1, "Select timed out" ); + } + else if ( nFound < 0) + { + Error( "Select error: %s", strerror(errno) ); + } + else + { for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) - FD_SET((*iter)->getReadDesc(),&rfds); - - mWriteable.clear(); - FD_ZERO(&wfds); + if ( FD_ISSET((*iter)->getReadDesc(),&rfds) ) + mReadable.push_back( *iter ); for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) - FD_SET((*iter)->getWriteDesc(),&wfds); - - int nFound = select( mMaxFd+1, &rfds, &wfds, NULL, selectTimeout ); - if( nFound == 0 ) - { - Debug( 1, "Select timed out" ); - } - else if ( nFound < 0) - { - Error( "Select error: %s", strerror(errno) ); - } - else - { - for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) - if ( FD_ISSET((*iter)->getReadDesc(),&rfds) ) - mReadable.push_back( *iter ); - for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) - if ( FD_ISSET((*iter)->getWriteDesc(),&rfds) ) - mWriteable.push_back( *iter ); - } - return( nFound ); + if ( FD_ISSET((*iter)->getWriteDesc(),&rfds) ) + mWriteable.push_back( *iter ); + } + return( nFound ); } const Select::CommsList &Select::getReadable() const { - return( mReadable ); + return( mReadable ); } const Select::CommsList &Select::getWriteable() const { - return( mWriteable ); + return( mWriteable ); } diff --git a/src/zm_comms.h b/src/zm_comms.h index ef1dda833..d0143917c 100644 --- a/src/zm_comms.h +++ b/src/zm_comms.h @@ -40,857 +40,857 @@ class CommsException : public Exception { public: - CommsException( const std::string &message ) : Exception( message ) - { - } + CommsException( const std::string &message ) : Exception( message ) + { + } }; class CommsBase { protected: - const int &mRd; - const int &mWd; + const int &mRd; + const int &mWd; protected: - CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) - { - } - virtual ~CommsBase() - { - } + CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) + { + } + virtual ~CommsBase() + { + } public: - virtual bool close()=0; - virtual bool isOpen() const=0; - virtual bool isClosed() const=0; - virtual bool setBlocking( bool blocking )=0; + virtual bool close()=0; + virtual bool isOpen() const=0; + virtual bool isClosed() const=0; + virtual bool setBlocking( bool blocking )=0; public: - int getReadDesc() const - { - return( mRd ); - } - int getWriteDesc() const - { - return( mWd ); - } - int getMaxDesc() const - { - return( mRd>mWd?mRd:mWd ); - } + int getReadDesc() const + { + return( mRd ); + } + int getWriteDesc() const + { + return( mWd ); + } + int getMaxDesc() const + { + return( mRd>mWd?mRd:mWd ); + } - virtual int read( void *msg, int len ) - { - ssize_t nBytes = ::read( mRd, msg, len ); - if ( nBytes < 0 ) - Debug( 1, "Read of %d bytes max on rd %d failed: %s", len, mRd, strerror(errno) ); - return( nBytes ); - } - virtual int write( const void *msg, int len ) - { - ssize_t nBytes = ::write( mWd, msg, len ); - if ( nBytes < 0 ) - Debug( 1, "Write of %d bytes on wd %d failed: %s", len, mWd, strerror(errno) ); - return( nBytes ); - } - virtual int readV( const struct iovec *iov, int iovcnt ) - { - int nBytes = ::readv( mRd, iov, iovcnt ); - if ( nBytes < 0 ) - Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) ); - return( nBytes ); - } - virtual int writeV( const struct iovec *iov, int iovcnt ) - { - ssize_t nBytes = ::writev( mWd, iov, iovcnt ); - if ( nBytes < 0 ) - Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) ); - return( nBytes ); - } - virtual int readV( int iovcnt, /* const void *msg1, int len1, */ ... ); - virtual int writeV( int iovcnt, /* const void *msg1, int len1, */ ... ); + virtual int read( void *msg, int len ) + { + ssize_t nBytes = ::read( mRd, msg, len ); + if ( nBytes < 0 ) + Debug( 1, "Read of %d bytes max on rd %d failed: %s", len, mRd, strerror(errno) ); + return( nBytes ); + } + virtual int write( const void *msg, int len ) + { + ssize_t nBytes = ::write( mWd, msg, len ); + if ( nBytes < 0 ) + Debug( 1, "Write of %d bytes on wd %d failed: %s", len, mWd, strerror(errno) ); + return( nBytes ); + } + virtual int readV( const struct iovec *iov, int iovcnt ) + { + int nBytes = ::readv( mRd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) ); + return( nBytes ); + } + virtual int writeV( const struct iovec *iov, int iovcnt ) + { + ssize_t nBytes = ::writev( mWd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) ); + return( nBytes ); + } + virtual int readV( int iovcnt, /* const void *msg1, int len1, */ ... ); + virtual int writeV( int iovcnt, /* const void *msg1, int len1, */ ... ); }; class Pipe : public CommsBase { protected: - int mFd[2]; + int mFd[2]; public: - Pipe() : CommsBase( mFd[0], mFd[1] ) - { - mFd[0] = -1; - mFd[1] = -1; - } - ~Pipe() - { - close(); - } + Pipe() : CommsBase( mFd[0], mFd[1] ) + { + mFd[0] = -1; + mFd[1] = -1; + } + ~Pipe() + { + close(); + } public: - bool open(); - bool close(); + bool open(); + bool close(); - bool isOpen() const - { - return( mFd[0] != -1 && mFd[1] != -1 ); - } - int getReadDesc() const - { - return( mFd[0] ); - } - int getWriteDesc() const - { - return( mFd[1] ); - } + bool isOpen() const + { + return( mFd[0] != -1 && mFd[1] != -1 ); + } + int getReadDesc() const + { + return( mFd[0] ); + } + int getWriteDesc() const + { + return( mFd[1] ); + } - bool setBlocking( bool blocking ); + bool setBlocking( bool blocking ); }; class SockAddr { private: - const struct sockaddr *mAddr; + const struct sockaddr *mAddr; public: - SockAddr( const struct sockaddr *addr ); - virtual ~SockAddr() - { - } + SockAddr( const struct sockaddr *addr ); + virtual ~SockAddr() + { + } - static SockAddr *newSockAddr( const struct sockaddr &addr, socklen_t len ); - static SockAddr *newSockAddr( const SockAddr *addr ); + static SockAddr *newSockAddr( const struct sockaddr &addr, socklen_t len ); + static SockAddr *newSockAddr( const SockAddr *addr ); - int getDomain() const - { - return( mAddr?mAddr->sa_family:AF_UNSPEC ); - } + int getDomain() const + { + return( mAddr?mAddr->sa_family:AF_UNSPEC ); + } - const struct sockaddr *getAddr() const - { - return( mAddr ); - } - virtual socklen_t getAddrSize() const=0; - virtual struct sockaddr *getTempAddr() const=0; + const struct sockaddr *getAddr() const + { + return( mAddr ); + } + virtual socklen_t getAddrSize() const=0; + virtual struct sockaddr *getTempAddr() const=0; }; class SockAddrInet : public SockAddr { private: - struct sockaddr_in mAddrIn; - struct sockaddr_in mTempAddrIn; + struct sockaddr_in mAddrIn; + struct sockaddr_in mTempAddrIn; public: - SockAddrInet(); - SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn ) - { - } - SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr ) - { - } + SockAddrInet(); + SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn ) + { + } + SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr ) + { + } - bool resolve( const char *host, const char *serv, const char *proto ); - bool resolve( const char *host, int port, const char *proto ); - bool resolve( const char *serv, const char *proto ); - bool resolve( int port, const char *proto ); + bool resolve( const char *host, const char *serv, const char *proto ); + bool resolve( const char *host, int port, const char *proto ); + bool resolve( const char *serv, const char *proto ); + bool resolve( int port, const char *proto ); - socklen_t getAddrSize() const - { - return( sizeof(mAddrIn) ); - } - struct sockaddr *getTempAddr() const - { - return( (sockaddr *)&mTempAddrIn ); - } + socklen_t getAddrSize() const + { + return( sizeof(mAddrIn) ); + } + struct sockaddr *getTempAddr() const + { + return( (sockaddr *)&mTempAddrIn ); + } public: - static socklen_t addrSize() - { - return( sizeof(sockaddr_in) ); - } + static socklen_t addrSize() + { + return( sizeof(sockaddr_in) ); + } }; class SockAddrUnix : public SockAddr { private: - struct sockaddr_un mAddrUn; - struct sockaddr_un mTempAddrUn; + struct sockaddr_un mAddrUn; + struct sockaddr_un mTempAddrUn; public: - SockAddrUnix(); - SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn ) - { - } - SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr ) - { - } + SockAddrUnix(); + SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn ) + { + } + SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr ) + { + } - bool resolve( const char *path, const char *proto ); + bool resolve( const char *path, const char *proto ); - socklen_t getAddrSize() const - { - return( sizeof(mAddrUn) ); - } - struct sockaddr *getTempAddr() const - { - return( (sockaddr *)&mTempAddrUn ); - } + socklen_t getAddrSize() const + { + return( sizeof(mAddrUn) ); + } + struct sockaddr *getTempAddr() const + { + return( (sockaddr *)&mTempAddrUn ); + } public: - static socklen_t addrSize() - { - return( sizeof(sockaddr_un) ); - } + static socklen_t addrSize() + { + return( sizeof(sockaddr_un) ); + } }; class Socket : public CommsBase { protected: - typedef enum { CLOSED, DISCONNECTED, LISTENING, CONNECTED } State; + typedef enum { CLOSED, DISCONNECTED, LISTENING, CONNECTED } State; protected: - int mSd; - State mState; - SockAddr *mLocalAddr; - SockAddr *mRemoteAddr; + int mSd; + State mState; + SockAddr *mLocalAddr; + SockAddr *mRemoteAddr; protected: - Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) - { - } - Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) - { - if ( socket.mLocalAddr ) - mLocalAddr = SockAddr::newSockAddr( mLocalAddr ); - if ( socket.mRemoteAddr ) - mRemoteAddr = SockAddr::newSockAddr( mRemoteAddr ); - } - virtual ~Socket() - { - close(); - delete mLocalAddr; - delete mRemoteAddr; - } + Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) + { + } + Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) + { + if ( socket.mLocalAddr ) + mLocalAddr = SockAddr::newSockAddr( mLocalAddr ); + if ( socket.mRemoteAddr ) + mRemoteAddr = SockAddr::newSockAddr( mRemoteAddr ); + } + virtual ~Socket() + { + close(); + delete mLocalAddr; + delete mRemoteAddr; + } public: - bool isOpen() const - { - return( !isClosed() ); - } - bool isClosed() const - { - return( mState == CLOSED ); - } - bool isDisconnected() const - { - return( mState == DISCONNECTED ); - } - bool isConnected() const - { - return( mState == CONNECTED ); - } - virtual bool close(); + bool isOpen() const + { + return( !isClosed() ); + } + bool isClosed() const + { + return( mState == CLOSED ); + } + bool isDisconnected() const + { + return( mState == DISCONNECTED ); + } + bool isConnected() const + { + return( mState == CONNECTED ); + } + virtual bool close(); protected: - bool isListening() const - { - return( mState == LISTENING ); - } + bool isListening() const + { + return( mState == LISTENING ); + } protected: - virtual bool socket(); - virtual bool bind(); + virtual bool socket(); + virtual bool bind(); protected: - virtual bool connect(); - virtual bool listen(); - virtual bool accept(); - virtual bool accept( int & ); + virtual bool connect(); + virtual bool listen(); + virtual bool accept(); + virtual bool accept( int & ); public: - virtual int send( const void *msg, int len ) const - { - ssize_t nBytes = ::send( mSd, msg, len, 0 ); - if ( nBytes < 0 ) - Debug( 1, "Send of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) ); - return( nBytes ); - } - virtual int recv( void *msg, int len ) const - { - ssize_t nBytes = ::recv( mSd, msg, len, 0 ); - if ( nBytes < 0 ) - Debug( 1, "Recv of %d bytes max on sd %d failed: %s", len, mSd, strerror(errno) ); - return( nBytes ); - } - virtual int send( const std::string &msg ) const - { - ssize_t nBytes = ::send( mSd, msg.data(), msg.size(), 0 ); - if ( nBytes < 0 ) - Debug( 1, "Send of string '%s' (%zd bytes) on sd %d failed: %s", msg.c_str(), msg.size(), mSd, strerror(errno) ); - return( nBytes ); - } - virtual int recv( std::string &msg ) const - { - char buffer[msg.capacity()]; - int nBytes = 0; - if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) - { - Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", sizeof(buffer), mSd, strerror(errno) ); - return( nBytes ); - } - buffer[nBytes] = '\0'; - msg = buffer; - return( nBytes ); - } - virtual int recv( std::string &msg, size_t maxLen ) const - { - char buffer[maxLen]; - int nBytes = 0; - if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) - { - Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno) ); - return( nBytes ); - } - buffer[nBytes] = '\0'; - msg = buffer; - return( nBytes ); - } - virtual int bytesToRead() const; - - int getDesc() const - { - return( mSd ); - } - //virtual bool isOpen() const - //{ - //return( mSd != -1 ); - //} - - virtual int getDomain() const=0; - virtual int getType() const=0; - virtual const char *getProtocol() const=0; - - const SockAddr *getLocalAddr() const + virtual int send( const void *msg, int len ) const + { + ssize_t nBytes = ::send( mSd, msg, len, 0 ); + if ( nBytes < 0 ) + Debug( 1, "Send of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) ); + return( nBytes ); + } + virtual int recv( void *msg, int len ) const + { + ssize_t nBytes = ::recv( mSd, msg, len, 0 ); + if ( nBytes < 0 ) + Debug( 1, "Recv of %d bytes max on sd %d failed: %s", len, mSd, strerror(errno) ); + return( nBytes ); + } + virtual int send( const std::string &msg ) const + { + ssize_t nBytes = ::send( mSd, msg.data(), msg.size(), 0 ); + if ( nBytes < 0 ) + Debug( 1, "Send of string '%s' (%zd bytes) on sd %d failed: %s", msg.c_str(), msg.size(), mSd, strerror(errno) ); + return( nBytes ); + } + virtual int recv( std::string &msg ) const + { + char buffer[msg.capacity()]; + int nBytes = 0; + if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) { - return( mLocalAddr ); + Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", sizeof(buffer), mSd, strerror(errno) ); + return( nBytes ); } - const SockAddr *getRemoteAddr() const + buffer[nBytes] = '\0'; + msg = buffer; + return( nBytes ); + } + virtual int recv( std::string &msg, size_t maxLen ) const + { + char buffer[maxLen]; + int nBytes = 0; + if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) { - return( mRemoteAddr ); + Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno) ); + return( nBytes ); } - virtual socklen_t getAddrSize() const=0; + buffer[nBytes] = '\0'; + msg = buffer; + return( nBytes ); + } + virtual int bytesToRead() const; - bool getBlocking( bool &blocking ); - bool setBlocking( bool blocking ); + int getDesc() const + { + return( mSd ); + } + //virtual bool isOpen() const + //{ + //return( mSd != -1 ); + //} - bool getSendBufferSize( int & ) const; - bool getRecvBufferSize( int & ) const; + virtual int getDomain() const=0; + virtual int getType() const=0; + virtual const char *getProtocol() const=0; - bool setSendBufferSize( int ); - bool setRecvBufferSize( int ); + const SockAddr *getLocalAddr() const + { + return( mLocalAddr ); + } + const SockAddr *getRemoteAddr() const + { + return( mRemoteAddr ); + } + virtual socklen_t getAddrSize() const=0; - bool getRouting( bool & ) const; - bool setRouting( bool ); + bool getBlocking( bool &blocking ); + bool setBlocking( bool blocking ); - bool getNoDelay( bool & ) const; - bool setNoDelay( bool ); + bool getSendBufferSize( int & ) const; + bool getRecvBufferSize( int & ) const; + + bool setSendBufferSize( int ); + bool setRecvBufferSize( int ); + + bool getRouting( bool & ) const; + bool setRouting( bool ); + + bool getNoDelay( bool & ) const; + bool setNoDelay( bool ); }; class InetSocket : virtual public Socket { public: - int getDomain() const - { - return( AF_INET ); - } - virtual socklen_t getAddrSize() const - { - return( SockAddrInet::addrSize() ); - } + int getDomain() const + { + return( AF_INET ); + } + virtual socklen_t getAddrSize() const + { + return( SockAddrInet::addrSize() ); + } protected: - bool resolveLocal( const char *host, const char *serv, const char *proto ) - { - SockAddrInet *addr = new SockAddrInet; - mLocalAddr = addr; - return( addr->resolve( host, serv, proto ) ); - } - bool resolveLocal( const char *host, int port, const char *proto ) - { - SockAddrInet *addr = new SockAddrInet; - mLocalAddr = addr; - return( addr->resolve( host, port, proto ) ); - } - bool resolveLocal( const char *serv, const char *proto ) - { - SockAddrInet *addr = new SockAddrInet; - mLocalAddr = addr; - return( addr->resolve( serv, proto ) ); - } - bool resolveLocal( int port, const char *proto ) - { - SockAddrInet *addr = new SockAddrInet; - mLocalAddr = addr; - return( addr->resolve( port, proto ) ); - } + bool resolveLocal( const char *host, const char *serv, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( host, serv, proto ) ); + } + bool resolveLocal( const char *host, int port, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( host, port, proto ) ); + } + bool resolveLocal( const char *serv, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( serv, proto ) ); + } + bool resolveLocal( int port, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( port, proto ) ); + } - bool resolveRemote( const char *host, const char *serv, const char *proto ) - { - SockAddrInet *addr = new SockAddrInet; - mRemoteAddr = addr; - return( addr->resolve( host, serv, proto ) ); - } - bool resolveRemote( const char *host, int port, const char *proto ) - { - SockAddrInet *addr = new SockAddrInet; - mRemoteAddr = addr; - return( addr->resolve( host, port, proto ) ); - } + bool resolveRemote( const char *host, const char *serv, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mRemoteAddr = addr; + return( addr->resolve( host, serv, proto ) ); + } + bool resolveRemote( const char *host, int port, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mRemoteAddr = addr; + return( addr->resolve( host, port, proto ) ); + } protected: - bool bind( const SockAddrInet &addr ) - { - mLocalAddr = new SockAddrInet( addr ); - return( Socket::bind() ); - } - bool bind( const char *host, const char *serv ) - { - if ( !resolveLocal( host, serv, getProtocol() ) ) - return( false ); - return( Socket::bind() ); - } - bool bind( const char *host, int port ) - { - if ( !resolveLocal( host, port, getProtocol() ) ) - return( false ); - return( Socket::bind() ); - } - bool bind( const char *serv ) - { - if ( !resolveLocal( serv, getProtocol() ) ) - return( false ); - return( Socket::bind() ); - } - bool bind( int port ) - { - if ( !resolveLocal( port, getProtocol() ) ) - return( false ); - return( Socket::bind() ); - } + bool bind( const SockAddrInet &addr ) + { + mLocalAddr = new SockAddrInet( addr ); + return( Socket::bind() ); + } + bool bind( const char *host, const char *serv ) + { + if ( !resolveLocal( host, serv, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + bool bind( const char *host, int port ) + { + if ( !resolveLocal( host, port, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + bool bind( const char *serv ) + { + if ( !resolveLocal( serv, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + bool bind( int port ) + { + if ( !resolveLocal( port, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } - bool connect( const SockAddrInet &addr ) - { - mRemoteAddr = new SockAddrInet( addr ); - return( Socket::connect() ); - } - bool connect( const char *host, const char *serv ) - { - if ( !resolveRemote( host, serv, getProtocol() ) ) - return( false ); - return( Socket::connect() ); - } - bool connect( const char *host, int port ) - { - if ( !resolveRemote( host, port, getProtocol() ) ) - return( false ); - return( Socket::connect() ); - } + bool connect( const SockAddrInet &addr ) + { + mRemoteAddr = new SockAddrInet( addr ); + return( Socket::connect() ); + } + bool connect( const char *host, const char *serv ) + { + if ( !resolveRemote( host, serv, getProtocol() ) ) + return( false ); + return( Socket::connect() ); + } + bool connect( const char *host, int port ) + { + if ( !resolveRemote( host, port, getProtocol() ) ) + return( false ); + return( Socket::connect() ); + } }; class UnixSocket : virtual public Socket { public: - int getDomain() const - { - return( AF_UNIX ); - } - virtual socklen_t getAddrSize() const - { - return( SockAddrUnix::addrSize() ); - } + int getDomain() const + { + return( AF_UNIX ); + } + virtual socklen_t getAddrSize() const + { + return( SockAddrUnix::addrSize() ); + } protected: - bool resolveLocal( const char *serv, const char *proto ) - { - SockAddrUnix *addr = new SockAddrUnix; - mLocalAddr = addr; - return( addr->resolve( serv, proto ) ); - } + bool resolveLocal( const char *serv, const char *proto ) + { + SockAddrUnix *addr = new SockAddrUnix; + mLocalAddr = addr; + return( addr->resolve( serv, proto ) ); + } - bool resolveRemote( const char *path, const char *proto ) - { - SockAddrUnix *addr = new SockAddrUnix; - mRemoteAddr = addr; - return( addr->resolve( path, proto ) ); - } + bool resolveRemote( const char *path, const char *proto ) + { + SockAddrUnix *addr = new SockAddrUnix; + mRemoteAddr = addr; + return( addr->resolve( path, proto ) ); + } protected: - bool bind( const char *path ) - { - if ( !UnixSocket::resolveLocal( path, getProtocol() ) ) - return( false ); - return( Socket::bind() ); - } + bool bind( const char *path ) + { + if ( !UnixSocket::resolveLocal( path, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } - bool connect( const char *path ) - { - if ( !UnixSocket::resolveRemote( path, getProtocol() ) ) - return( false ); - return( Socket::connect() ); - } + bool connect( const char *path ) + { + if ( !UnixSocket::resolveRemote( path, getProtocol() ) ) + return( false ); + return( Socket::connect() ); + } }; class UdpSocket : virtual public Socket { public: - int getType() const - { - return( SOCK_DGRAM ); - } - const char *getProtocol() const - { - return( "udp" ); - } + int getType() const + { + return( SOCK_DGRAM ); + } + const char *getProtocol() const + { + return( "udp" ); + } public: - virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const - { - ssize_t nBytes = ::sendto( mSd, msg, len, 0, addr?addr->getAddr():NULL, addr?addr->getAddrSize():0 ); - if ( nBytes < 0 ) - Debug( 1, "Sendto of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) ); - return( nBytes ); - } - virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const - { - ssize_t nBytes = 0; - if ( addr ) - { - struct sockaddr sockAddr; - socklen_t sockLen; - nBytes = ::recvfrom( mSd, msg, len, 0, &sockAddr, &sockLen ); - if ( nBytes < 0 ) - { - Debug( 1, "Recvfrom of %d bytes max on sd %d (with address) failed: %s", len, mSd, strerror(errno) ); - } - else if ( sockLen ) - { - addr = SockAddr::newSockAddr( sockAddr, sockLen ); - } - } - else - { - nBytes = ::recvfrom( mSd, msg, len, 0, NULL, 0 ); - if ( nBytes < 0 ) - Debug( 1, "Recvfrom of %d bytes max on sd %d (no address) failed: %s", len, mSd, strerror(errno) ); - } - return( nBytes ); - } + virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const + { + ssize_t nBytes = ::sendto( mSd, msg, len, 0, addr?addr->getAddr():NULL, addr?addr->getAddrSize():0 ); + if ( nBytes < 0 ) + Debug( 1, "Sendto of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) ); + return( nBytes ); + } + virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const + { + ssize_t nBytes = 0; + if ( addr ) + { + struct sockaddr sockAddr; + socklen_t sockLen; + nBytes = ::recvfrom( mSd, msg, len, 0, &sockAddr, &sockLen ); + if ( nBytes < 0 ) + { + Debug( 1, "Recvfrom of %d bytes max on sd %d (with address) failed: %s", len, mSd, strerror(errno) ); + } + else if ( sockLen ) + { + addr = SockAddr::newSockAddr( sockAddr, sockLen ); + } + } + else + { + nBytes = ::recvfrom( mSd, msg, len, 0, NULL, 0 ); + if ( nBytes < 0 ) + Debug( 1, "Recvfrom of %d bytes max on sd %d (no address) failed: %s", len, mSd, strerror(errno) ); + } + return( nBytes ); + } }; class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket { public: - bool bind( const SockAddrInet &addr ) - { - return( InetSocket::bind( addr ) ); - } - bool bind( const char *host, const char *serv ) - { - return( InetSocket::bind( host, serv ) ); - } - bool bind( const char *host, int port ) - { - return( InetSocket::bind( host, port ) ); - } - bool bind( const char *serv ) - { - return( InetSocket::bind( serv ) ); - } - bool bind( int port ) - { - return( InetSocket::bind( port ) ); - } + bool bind( const SockAddrInet &addr ) + { + return( InetSocket::bind( addr ) ); + } + bool bind( const char *host, const char *serv ) + { + return( InetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( InetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( InetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( InetSocket::bind( port ) ); + } - bool connect( const SockAddrInet &addr ) - { - return( InetSocket::connect( addr ) ); - } - bool connect( const char *host, const char *serv ) - { - return( InetSocket::connect( host, serv ) ); - } - bool connect( const char *host, int port ) - { - return( InetSocket::connect( host, port ) ); - } + bool connect( const SockAddrInet &addr ) + { + return( InetSocket::connect( addr ) ); + } + bool connect( const char *host, const char *serv ) + { + return( InetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( InetSocket::connect( host, port ) ); + } }; class UdpUnixSocket : virtual public UdpSocket, virtual public UnixSocket { public: - bool bind( const char *path ) - { - return( UnixSocket::bind( path ) ); - } + bool bind( const char *path ) + { + return( UnixSocket::bind( path ) ); + } - bool connect( const char *path ) - { - return( UnixSocket::connect( path ) ); - } + bool connect( const char *path ) + { + return( UnixSocket::connect( path ) ); + } }; class UdpInetClient : public UdpInetSocket { protected: - bool bind( const SockAddrInet &addr ) - { - return( UdpInetSocket::bind( addr ) ); - } - bool bind( const char *host, const char *serv ) - { - return( UdpInetSocket::bind( host, serv ) ); - } - bool bind( const char *host, int port ) - { - return( UdpInetSocket::bind( host, port ) ); - } - bool bind( const char *serv ) - { - return( UdpInetSocket::bind( serv ) ); - } - bool bind( int port ) - { - return( UdpInetSocket::bind( port ) ); - } + bool bind( const SockAddrInet &addr ) + { + return( UdpInetSocket::bind( addr ) ); + } + bool bind( const char *host, const char *serv ) + { + return( UdpInetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( UdpInetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( UdpInetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( UdpInetSocket::bind( port ) ); + } public: - bool connect( const SockAddrInet &addr ) - { - return( UdpInetSocket::connect( addr ) ); - } - bool connect( const char *host, const char *serv ) - { - return( UdpInetSocket::connect( host, serv ) ); - } - bool connect( const char *host, int port ) - { - return( UdpInetSocket::connect( host, port ) ); - } + bool connect( const SockAddrInet &addr ) + { + return( UdpInetSocket::connect( addr ) ); + } + bool connect( const char *host, const char *serv ) + { + return( UdpInetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( UdpInetSocket::connect( host, port ) ); + } }; class UdpUnixClient : public UdpUnixSocket { public: - bool bind( const char *path ) - { - return( UdpUnixSocket::bind( path ) ); - } + bool bind( const char *path ) + { + return( UdpUnixSocket::bind( path ) ); + } public: - bool connect( const char *path ) - { - return( UdpUnixSocket::connect( path) ); - } + bool connect( const char *path ) + { + return( UdpUnixSocket::connect( path) ); + } }; class UdpInetServer : public UdpInetSocket { public: - bool bind( const SockAddrInet &addr ) - { - return( UdpInetSocket::bind( addr ) ); - } - bool bind( const char *host, const char *serv ) - { - return( UdpInetSocket::bind( host, serv ) ); - } - bool bind( const char *host, int port ) - { - return( UdpInetSocket::bind( host, port ) ); - } - bool bind( const char *serv ) - { - return( UdpInetSocket::bind( serv ) ); - } - bool bind( int port ) - { - return( UdpInetSocket::bind( port ) ); - } + bool bind( const SockAddrInet &addr ) + { + return( UdpInetSocket::bind( addr ) ); + } + bool bind( const char *host, const char *serv ) + { + return( UdpInetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( UdpInetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( UdpInetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( UdpInetSocket::bind( port ) ); + } protected: - bool connect( const char *host, const char *serv ) - { - return( UdpInetSocket::connect( host, serv ) ); - } - bool connect( const char *host, int port ) - { - return( UdpInetSocket::connect( host, port ) ); - } + bool connect( const char *host, const char *serv ) + { + return( UdpInetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( UdpInetSocket::connect( host, port ) ); + } }; class UdpUnixServer : public UdpUnixSocket { public: - bool bind( const char *path ) - { - return( UdpUnixSocket::bind( path ) ); - } + bool bind( const char *path ) + { + return( UdpUnixSocket::bind( path ) ); + } protected: - bool connect( const char *path ) - { - return( UdpUnixSocket::connect( path ) ); - } + bool connect( const char *path ) + { + return( UdpUnixSocket::connect( path ) ); + } }; class TcpSocket : virtual public Socket { public: - TcpSocket() - { - } - TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd ) - { - } + TcpSocket() + { + } + TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd ) + { + } public: - int getType() const - { - return( SOCK_STREAM ); - } - const char *getProtocol() const - { - return( "tcp" ); - } + int getType() const + { + return( SOCK_STREAM ); + } + const char *getProtocol() const + { + return( "tcp" ); + } }; class TcpInetSocket : virtual public TcpSocket, virtual public InetSocket { public: - TcpInetSocket() - { - } - TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd ) - { - } + TcpInetSocket() + { + } + TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd ) + { + } }; class TcpUnixSocket : virtual public TcpSocket, virtual public UnixSocket { public: - TcpUnixSocket() - { - } - TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd ) - { - } + TcpUnixSocket() + { + } + TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd ) + { + } }; class TcpInetClient : public TcpInetSocket { public: - bool connect( const char *host, const char *serv ) - { - return( TcpInetSocket::connect( host, serv ) ); - } - bool connect( const char *host, int port ) - { - return( TcpInetSocket::connect( host, port ) ); - } + bool connect( const char *host, const char *serv ) + { + return( TcpInetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( TcpInetSocket::connect( host, port ) ); + } }; class TcpUnixClient : public TcpUnixSocket { public: - bool connect( const char *path ) - { - return( TcpUnixSocket::connect( path) ); - } + bool connect( const char *path ) + { + return( TcpUnixSocket::connect( path) ); + } }; class TcpInetServer : public TcpInetSocket { public: - bool bind( const char *host, const char *serv ) - { - return( TcpInetSocket::bind( host, serv ) ); - } - bool bind( const char *host, int port ) - { - return( TcpInetSocket::bind( host, port ) ); - } - bool bind( const char *serv ) - { - return( TcpInetSocket::bind( serv ) ); - } - bool bind( int port ) - { - return( TcpInetSocket::bind( port ) ); - } + bool bind( const char *host, const char *serv ) + { + return( TcpInetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( TcpInetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( TcpInetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( TcpInetSocket::bind( port ) ); + } public: - bool isListening() const { return( Socket::isListening() ); } - bool listen(); - bool accept(); - bool accept( TcpInetSocket *&newSocket ); + bool isListening() const { return( Socket::isListening() ); } + bool listen(); + bool accept(); + bool accept( TcpInetSocket *&newSocket ); }; class TcpUnixServer : public TcpUnixSocket { public: - bool bind( const char *path ) - { - return( TcpUnixSocket::bind( path ) ); - } + bool bind( const char *path ) + { + return( TcpUnixSocket::bind( path ) ); + } public: - bool isListening() const { return( Socket::isListening() ); } - bool listen(); - bool accept(); - bool accept( TcpUnixSocket *&newSocket ); + bool isListening() const { return( Socket::isListening() ); } + bool listen(); + bool accept(); + bool accept( TcpUnixSocket *&newSocket ); }; class Select { public: - typedef std::set CommsSet; - typedef std::vector CommsList; + typedef std::set CommsSet; + typedef std::vector CommsList; protected: - CommsSet mReaders; - CommsSet mWriters; - CommsList mReadable; - CommsList mWriteable; - bool mHasTimeout; - struct timeval mTimeout; - int mMaxFd; + CommsSet mReaders; + CommsSet mWriters; + CommsList mReadable; + CommsList mWriteable; + bool mHasTimeout; + struct timeval mTimeout; + int mMaxFd; public: - Select(); - Select( struct timeval timeout ); - Select( int timeout ); - Select( double timeout ); + Select(); + Select( struct timeval timeout ); + Select( int timeout ); + Select( double timeout ); - void setTimeout( int timeout ); - void setTimeout( double timeout ); - void setTimeout( struct timeval timeout ); - void clearTimeout(); + void setTimeout( int timeout ); + void setTimeout( double timeout ); + void setTimeout( struct timeval timeout ); + void clearTimeout(); - void calcMaxFd(); + void calcMaxFd(); - bool addReader( CommsBase *comms ); - bool deleteReader( CommsBase *comms ); - void clearReaders(); + bool addReader( CommsBase *comms ); + bool deleteReader( CommsBase *comms ); + void clearReaders(); - bool addWriter( CommsBase *comms ); - bool deleteWriter( CommsBase *comms ); - void clearWriters(); + bool addWriter( CommsBase *comms ); + bool deleteWriter( CommsBase *comms ); + void clearWriters(); - int wait(); + int wait(); - const CommsList &getReadable() const; - const CommsList &getWriteable() const; + const CommsList &getReadable() const; + const CommsList &getWriteable() const; }; #endif // ZM_COMMS_H diff --git a/src/zm_config.cpp b/src/zm_config.cpp index 5a7454a7b..26051f113 100644 --- a/src/zm_config.cpp +++ b/src/zm_config.cpp @@ -29,277 +29,277 @@ void zmLoadConfig() { - FILE *cfg; - char line[512]; - if ( (cfg = fopen( ZM_CONFIG, "r")) == NULL ) - { - Fatal( "Can't open %s: %s", ZM_CONFIG, strerror(errno) ); - } - while ( fgets( line, sizeof(line), cfg ) != NULL ) - { - char *line_ptr = line; + FILE *cfg; + char line[512]; + if ( (cfg = fopen( ZM_CONFIG, "r")) == NULL ) + { + Fatal( "Can't open %s: %s", ZM_CONFIG, strerror(errno) ); + } + while ( fgets( line, sizeof(line), cfg ) != NULL ) + { + char *line_ptr = line; - // Trim off any cr/lf line endings - int chomp_len = strcspn( line_ptr, "\r\n" ); - line_ptr[chomp_len] = '\0'; + // Trim off any cr/lf line endings + int chomp_len = strcspn( line_ptr, "\r\n" ); + line_ptr[chomp_len] = '\0'; - // Remove leading white space - int white_len = strspn( line_ptr, " \t" ); - line_ptr += white_len; + // Remove leading white space + int white_len = strspn( line_ptr, " \t" ); + line_ptr += white_len; - // Check for comment or empty line - if ( *line_ptr == '\0' || *line_ptr == '#' ) - continue; + // Check for comment or empty line + if ( *line_ptr == '\0' || *line_ptr == '#' ) + continue; - // Remove trailing white space - char *temp_ptr = line_ptr+strlen(line_ptr)-1; - while ( *temp_ptr == ' ' || *temp_ptr == '\t' ) - { - *temp_ptr-- = '\0'; - temp_ptr--; - } + // Remove trailing white space + char *temp_ptr = line_ptr+strlen(line_ptr)-1; + while ( *temp_ptr == ' ' || *temp_ptr == '\t' ) + { + *temp_ptr-- = '\0'; + temp_ptr--; + } - // Now look for the '=' in the middle of the line - temp_ptr = strchr( line_ptr, '=' ); - if ( !temp_ptr ) - { - Warning( "Invalid data in %s: '%s'", ZM_CONFIG, line ); - continue; - } + // Now look for the '=' in the middle of the line + temp_ptr = strchr( line_ptr, '=' ); + if ( !temp_ptr ) + { + Warning( "Invalid data in %s: '%s'", ZM_CONFIG, line ); + continue; + } - // Assign the name and value parts - char *name_ptr = line_ptr; - char *val_ptr = temp_ptr+1; + // Assign the name and value parts + char *name_ptr = line_ptr; + char *val_ptr = temp_ptr+1; - // Trim trailing space from the name part - do - { - *temp_ptr = '\0'; - temp_ptr--; - } - while ( *temp_ptr == ' ' || *temp_ptr == '\t' ); + // Trim trailing space from the name part + do + { + *temp_ptr = '\0'; + temp_ptr--; + } + while ( *temp_ptr == ' ' || *temp_ptr == '\t' ); - // Remove leading white space from the value part - white_len = strspn( val_ptr, " \t" ); - val_ptr += white_len; + // Remove leading white space from the value part + white_len = strspn( val_ptr, " \t" ); + val_ptr += white_len; - if ( strcasecmp( name_ptr, "ZM_DB_HOST" ) == 0 ) - staticConfig.DB_HOST = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_DB_NAME" ) == 0 ) - staticConfig.DB_NAME = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_DB_USER" ) == 0 ) - staticConfig.DB_USER = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_DB_PASS" ) == 0 ) - staticConfig.DB_PASS = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 ) - staticConfig.PATH_WEB = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_SERVER_HOST" ) == 0 ) - staticConfig.SERVER_NAME = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_SERVER_NAME" ) == 0 ) - staticConfig.SERVER_NAME = std::string(val_ptr); - else if ( strcasecmp( name_ptr, "ZM_SERVER_ID" ) == 0 ) - staticConfig.SERVER_ID = atoi(val_ptr); - else - { - // We ignore this now as there may be more parameters than the - // c/c++ binaries are bothered about - // Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG ); - } - } // end foreach line of the config - fclose( cfg ); - zmDbConnect(); - config.Load(); - config.Assign(); + if ( strcasecmp( name_ptr, "ZM_DB_HOST" ) == 0 ) + staticConfig.DB_HOST = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_DB_NAME" ) == 0 ) + staticConfig.DB_NAME = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_DB_USER" ) == 0 ) + staticConfig.DB_USER = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_DB_PASS" ) == 0 ) + staticConfig.DB_PASS = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 ) + staticConfig.PATH_WEB = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_SERVER_HOST" ) == 0 ) + staticConfig.SERVER_NAME = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_SERVER_NAME" ) == 0 ) + staticConfig.SERVER_NAME = std::string(val_ptr); + else if ( strcasecmp( name_ptr, "ZM_SERVER_ID" ) == 0 ) + staticConfig.SERVER_ID = atoi(val_ptr); + else + { + // We ignore this now as there may be more parameters than the + // c/c++ binaries are bothered about + // Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG ); + } + } // end foreach line of the config + fclose( cfg ); + zmDbConnect(); + config.Load(); + config.Assign(); - // Populate the server config entries - if ( ! staticConfig.SERVER_ID ) { - if ( ! staticConfig.SERVER_NAME.empty() ) { + // Populate the server config entries + if ( ! staticConfig.SERVER_ID ) { + if ( ! staticConfig.SERVER_NAME.empty() ) { - Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() ); - std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); - if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { - staticConfig.SERVER_ID = atoi(dbrow[0]); - } else { - Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); - } + Debug( 1, "Fetching ZM_SERVER_ID For Name = %s", staticConfig.SERVER_NAME.c_str() ); + std::string sql = stringtf("SELECT Id FROM Servers WHERE Name='%s'", staticConfig.SERVER_NAME.c_str() ); + if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { + staticConfig.SERVER_ID = atoi(dbrow[0]); + } else { + Fatal("Can't get ServerId for Server %s", staticConfig.SERVER_NAME.c_str() ); + } - } // end if has SERVER_NAME - } else if ( staticConfig.SERVER_NAME.empty() ) { - Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID ); - std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); - - if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { - staticConfig.SERVER_NAME = std::string(dbrow[0]); - } else { - Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); - } - - } - if ( ! staticConfig.SERVER_ID ) { - Debug( 1, "No Server ID or Name specified in config. Not using Multi-Server Mode." ); - } else { - Debug( 1, "Server is %d: using Multi-Server Mode.", staticConfig.SERVER_ID ); - } + } // end if has SERVER_NAME + } else if ( staticConfig.SERVER_NAME.empty() ) { + Debug( 1, "Fetching ZM_SERVER_NAME For Id = %d", staticConfig.SERVER_ID ); + std::string sql = stringtf("SELECT Name FROM Servers WHERE Id='%d'", staticConfig.SERVER_ID ); + + if ( MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ) ) { + staticConfig.SERVER_NAME = std::string(dbrow[0]); + } else { + Fatal("Can't get ServerName for Server ID %d", staticConfig.SERVER_ID ); + } + + } + if ( ! staticConfig.SERVER_ID ) { + Debug( 1, "No Server ID or Name specified in config. Not using Multi-Server Mode." ); + } else { + Debug( 1, "Server is %d: using Multi-Server Mode.", staticConfig.SERVER_ID ); + } } StaticConfig staticConfig; ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *const p_type ) { - name = new char[strlen(p_name)+1]; - strcpy( name, p_name ); - value = new char[strlen(p_value)+1]; - strcpy( value, p_value ); - type = new char[strlen(p_type)+1]; - strcpy( type, p_type ); + name = new char[strlen(p_name)+1]; + strcpy( name, p_name ); + value = new char[strlen(p_value)+1]; + strcpy( value, p_value ); + type = new char[strlen(p_type)+1]; + strcpy( type, p_type ); - //Info( "Created new config item %s = %s (%s)\n", name, value, type ); + //Info( "Created new config item %s = %s (%s)\n", name, value, type ); - accessed = false; + accessed = false; } ConfigItem::~ConfigItem() { - delete[] name; - delete[] value; - delete[] type; + delete[] name; + delete[] value; + delete[] type; } void ConfigItem::ConvertValue() const { - if ( !strcmp( type, "boolean" ) ) - { - cfg_type = CFG_BOOLEAN; - cfg_value.boolean_value = (bool)strtol( value, 0, 0 ); - } - else if ( !strcmp( type, "integer" ) ) - { - cfg_type = CFG_INTEGER; - cfg_value.integer_value = strtol( value, 0, 10 ); - } - else if ( !strcmp( type, "hexadecimal" ) ) - { - cfg_type = CFG_INTEGER; - cfg_value.integer_value = strtol( value, 0, 16 ); - } - else if ( !strcmp( type, "decimal" ) ) - { - cfg_type = CFG_DECIMAL; - cfg_value.decimal_value = strtod( value, 0 ); - } - else - { - cfg_type = CFG_STRING; - cfg_value.string_value = value; - } - accessed = true; + if ( !strcmp( type, "boolean" ) ) + { + cfg_type = CFG_BOOLEAN; + cfg_value.boolean_value = (bool)strtol( value, 0, 0 ); + } + else if ( !strcmp( type, "integer" ) ) + { + cfg_type = CFG_INTEGER; + cfg_value.integer_value = strtol( value, 0, 10 ); + } + else if ( !strcmp( type, "hexadecimal" ) ) + { + cfg_type = CFG_INTEGER; + cfg_value.integer_value = strtol( value, 0, 16 ); + } + else if ( !strcmp( type, "decimal" ) ) + { + cfg_type = CFG_DECIMAL; + cfg_value.decimal_value = strtod( value, 0 ); + } + else + { + cfg_type = CFG_STRING; + cfg_value.string_value = value; + } + accessed = true; } bool ConfigItem::BooleanValue() const { - if ( !accessed ) - ConvertValue(); + if ( !accessed ) + ConvertValue(); - if ( cfg_type != CFG_BOOLEAN ) - { - Error( "Attempt to fetch boolean value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); - exit( -1 ); - } + if ( cfg_type != CFG_BOOLEAN ) + { + Error( "Attempt to fetch boolean value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } - return( cfg_value.boolean_value ); + return( cfg_value.boolean_value ); } int ConfigItem::IntegerValue() const { - if ( !accessed ) - ConvertValue(); + if ( !accessed ) + ConvertValue(); - if ( cfg_type != CFG_INTEGER ) - { - Error( "Attempt to fetch integer value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); - exit( -1 ); - } + if ( cfg_type != CFG_INTEGER ) + { + Error( "Attempt to fetch integer value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } - return( cfg_value.integer_value ); + return( cfg_value.integer_value ); } double ConfigItem::DecimalValue() const { - if ( !accessed ) - ConvertValue(); + if ( !accessed ) + ConvertValue(); - if ( cfg_type != CFG_DECIMAL ) - { - Error( "Attempt to fetch decimal value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); - exit( -1 ); - } + if ( cfg_type != CFG_DECIMAL ) + { + Error( "Attempt to fetch decimal value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } - return( cfg_value.decimal_value ); + return( cfg_value.decimal_value ); } const char *ConfigItem::StringValue() const { - if ( !accessed ) - ConvertValue(); + if ( !accessed ) + ConvertValue(); - if ( cfg_type != CFG_STRING ) - { - Error( "Attempt to fetch string value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); - exit( -1 ); - } + if ( cfg_type != CFG_STRING ) + { + Error( "Attempt to fetch string value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } - return( cfg_value.string_value ); + return( cfg_value.string_value ); } Config::Config() { - n_items = 0; - items = 0; + n_items = 0; + items = 0; } Config::~Config() { - if ( items ) - { - for ( int i = 0; i < n_items; i++ ) - { - delete items[i]; - } - delete[] items; - } + if ( items ) + { + for ( int i = 0; i < n_items; i++ ) + { + delete items[i]; + } + delete[] items; + } } void Config::Load() { - static char sql[ZM_SQL_SML_BUFSIZ]; + static char sql[ZM_SQL_SML_BUFSIZ]; - strncpy( sql, "select Name, Value, Type from Config order by Id", sizeof(sql) ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + strncpy( sql, "select Name, Value, Type from Config order by Id", sizeof(sql) ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - n_items = mysql_num_rows( result ); + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + n_items = mysql_num_rows( result ); - if ( n_items <= ZM_MAX_CFG_ID ) - { - Error( "Config mismatch, expected %d items, read %d. Try running 'zmupdate.pl -f' to reload config.", ZM_MAX_CFG_ID+1, n_items ); - exit( -1 ); - } + if ( n_items <= ZM_MAX_CFG_ID ) + { + Error( "Config mismatch, expected %d items, read %d. Try running 'zmupdate.pl -f' to reload config.", ZM_MAX_CFG_ID+1, n_items ); + exit( -1 ); + } - items = new ConfigItem *[n_items]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - items[i] = new ConfigItem( dbrow[0], dbrow[1], dbrow[2] ); - } - mysql_free_result( result ); + items = new ConfigItem *[n_items]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + items[i] = new ConfigItem( dbrow[0], dbrow[1], dbrow[2] ); + } + mysql_free_result( result ); } void Config::Assign() @@ -309,27 +309,27 @@ ZM_CFG_ASSIGN_LIST const ConfigItem &Config::Item( int id ) { - if ( !n_items ) - { - Load(); - Assign(); - } + if ( !n_items ) + { + Load(); + Assign(); + } - if ( id < 0 || id > ZM_MAX_CFG_ID ) - { - Error( "Attempt to access invalid config, id = %d. Try running 'zmupdate.pl -f' to reload config.", id ); - exit( -1 ); - } + if ( id < 0 || id > ZM_MAX_CFG_ID ) + { + Error( "Attempt to access invalid config, id = %d. Try running 'zmupdate.pl -f' to reload config.", id ); + exit( -1 ); + } - ConfigItem *item = items[id]; - - if ( !item ) - { - Error( "Can't find config item %d", id ); - exit( -1 ); - } - - return( *item ); + ConfigItem *item = items[id]; + + if ( !item ) + { + Error( "Can't find config item %d", id ); + exit( -1 ); + } + + return( *item ); } Config config; diff --git a/src/zm_config.h.in b/src/zm_config.h.in index 83aa19210..1deeff861 100644 --- a/src/zm_config.h.in +++ b/src/zm_config.h.in @@ -25,48 +25,48 @@ #include -#define ZM_CONFIG "@ZM_CONFIG@" // Path to config file -#define ZM_VERSION "@VERSION@" // ZoneMinder Version +#define ZM_CONFIG "@ZM_CONFIG@" // Path to config file +#define ZM_VERSION "@VERSION@" // ZoneMinder Version -#define ZM_HAS_V4L1 @ZM_HAS_V4L1@ -#define ZM_HAS_V4L2 @ZM_HAS_V4L2@ -#define ZM_HAS_V4L @ZM_HAS_V4L@ +#define ZM_HAS_V4L1 @ZM_HAS_V4L1@ +#define ZM_HAS_V4L2 @ZM_HAS_V4L2@ +#define ZM_HAS_V4L @ZM_HAS_V4L@ #ifdef HAVE_LIBAVFORMAT -#define ZM_HAS_FFMPEG 1 +#define ZM_HAS_FFMPEG 1 #endif // HAVE_LIBAVFORMAT -#define ZM_MAX_IMAGE_WIDTH 2048 // The largest image we imagine ever handling -#define ZM_MAX_IMAGE_HEIGHT 1536 // The largest image we imagine ever handling -#define ZM_MAX_IMAGE_COLOURS 4 // The largest image we imagine ever handling -#define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT) -#define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS) +#define ZM_MAX_IMAGE_WIDTH 2048 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_HEIGHT 1536 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_COLOURS 4 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT) +#define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS) -#define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP -#define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP +#define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP +#define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP -#define ZM_SQL_BATCH_SIZE 50 // Limit the size of multi-row SQL statements -#define ZM_SQL_SML_BUFSIZ 256 // Size of SQL buffer -#define ZM_SQL_MED_BUFSIZ 1024 // Size of SQL buffer -#define ZM_SQL_LGE_BUFSIZ 8192 // Size of SQL buffer +#define ZM_SQL_BATCH_SIZE 50 // Limit the size of multi-row SQL statements +#define ZM_SQL_SML_BUFSIZ 256 // Size of SQL buffer +#define ZM_SQL_MED_BUFSIZ 1024 // Size of SQL buffer +#define ZM_SQL_LGE_BUFSIZ 8192 // Size of SQL buffer -#define ZM_NETWORK_BUFSIZ 32768 // Size of network buffer +#define ZM_NETWORK_BUFSIZ 32768 // Size of network buffer -#define ZM_MAX_FPS 30 // The maximum frame rate we expect to handle -#define ZM_SAMPLE_RATE int(1000000/ZM_MAX_FPS) // A general nyquist sample frequency for delays etc -#define ZM_SUSPENDED_RATE int(1000000/4) // A slower rate for when disabled etc +#define ZM_MAX_FPS 30 // The maximum frame rate we expect to handle +#define ZM_SAMPLE_RATE int(1000000/ZM_MAX_FPS) // A general nyquist sample frequency for delays etc +#define ZM_SUSPENDED_RATE int(1000000/4) // A slower rate for when disabled etc extern void zmLoadConfig(); struct StaticConfig { - std::string DB_HOST; - std::string DB_NAME; - std::string DB_USER; - std::string DB_PASS; - std::string PATH_WEB; - std::string SERVER_NAME; - unsigned int SERVER_ID; + std::string DB_HOST; + std::string DB_NAME; + std::string DB_USER; + std::string DB_PASS; + std::string PATH_WEB; + std::string SERVER_NAME; + unsigned int SERVER_ID; }; extern StaticConfig staticConfig; @@ -74,63 +74,63 @@ extern StaticConfig staticConfig; class ConfigItem { private: - char *name; - char *value; - char *type; + char *name; + char *value; + char *type; - mutable enum { CFG_BOOLEAN, CFG_INTEGER, CFG_DECIMAL, CFG_STRING } cfg_type; - mutable union - { - bool boolean_value; - int integer_value; - double decimal_value; - char *string_value; - } cfg_value; - mutable bool accessed; + mutable enum { CFG_BOOLEAN, CFG_INTEGER, CFG_DECIMAL, CFG_STRING } cfg_type; + mutable union + { + bool boolean_value; + int integer_value; + double decimal_value; + char *string_value; + } cfg_value; + mutable bool accessed; public: - ConfigItem( const char *p_name, const char *p_value, const char *const p_type ); - ~ConfigItem(); - void ConvertValue() const; - bool BooleanValue() const; - int IntegerValue() const; - double DecimalValue() const; - const char *StringValue() const; + ConfigItem( const char *p_name, const char *p_value, const char *const p_type ); + ~ConfigItem(); + void ConvertValue() const; + bool BooleanValue() const; + int IntegerValue() const; + double DecimalValue() const; + const char *StringValue() const; - inline operator bool() const - { - return( BooleanValue() ); - } - inline operator int() const - { - return( IntegerValue() ); - } - inline operator double() const - { - return( DecimalValue() ); - } - inline operator const char *() const - { - return( StringValue() ); - } + inline operator bool() const + { + return( BooleanValue() ); + } + inline operator int() const + { + return( IntegerValue() ); + } + inline operator double() const + { + return( DecimalValue() ); + } + inline operator const char *() const + { + return( StringValue() ); + } }; class Config { public: - ZM_CFG_DECLARE_LIST + ZM_CFG_DECLARE_LIST private: - int n_items; - ConfigItem **items; + int n_items; + ConfigItem **items; public: - Config(); - ~Config(); + Config(); + ~Config(); - void Load(); - void Assign(); - const ConfigItem &Item( int id ); + void Load(); + void Assign(); + const ConfigItem &Item( int id ); }; extern Config config; diff --git a/src/zm_coord.h b/src/zm_coord.h index 6a6620529..7316244a2 100644 --- a/src/zm_coord.h +++ b/src/zm_coord.h @@ -28,40 +28,40 @@ class Coord { private: - int x, y; + int x, y; public: - inline Coord() : x(0), y(0) - { - } - inline Coord( int p_x, int p_y ) : x(p_x), y(p_y) - { - } - inline Coord( const Coord &p_coord ) : x(p_coord.x), y(p_coord.y) - { - } - inline int &X() { return( x ); } - inline const int &X() const { return( x ); } - inline int &Y() { return( y ); } - inline const int &Y() const { return( y ); } + inline Coord() : x(0), y(0) + { + } + inline Coord( int p_x, int p_y ) : x(p_x), y(p_y) + { + } + inline Coord( const Coord &p_coord ) : x(p_coord.x), y(p_coord.y) + { + } + inline int &X() { return( x ); } + inline const int &X() const { return( x ); } + inline int &Y() { return( y ); } + inline const int &Y() const { return( y ); } - inline static Coord Range( const Coord &coord1, const Coord &coord2 ) - { - Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 ); - return( result ); - } + inline static Coord Range( const Coord &coord1, const Coord &coord2 ) + { + Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 ); + return( result ); + } - inline bool operator==( const Coord &coord ) { return( x == coord.x && y == coord.y ); } - inline bool operator!=( const Coord &coord ) { return( x != coord.x || y != coord.y ); } - inline bool operator>( const Coord &coord ) { return( x > coord.x && y > coord.y ); } - inline bool operator>=( const Coord &coord ) { return( !(operator<(coord)) ); } - inline bool operator<( const Coord &coord ) { return( x < coord.x && y < coord.y ); } - inline bool operator<=( const Coord &coord ) { return( !(operator>(coord)) ); } - inline Coord &operator+=( const Coord &coord ) { x += coord.x; y += coord.y; return( *this ); } - inline Coord &operator-=( const Coord &coord ) { x -= coord.x; y -= coord.y; return( *this ); } + inline bool operator==( const Coord &coord ) { return( x == coord.x && y == coord.y ); } + inline bool operator!=( const Coord &coord ) { return( x != coord.x || y != coord.y ); } + inline bool operator>( const Coord &coord ) { return( x > coord.x && y > coord.y ); } + inline bool operator>=( const Coord &coord ) { return( !(operator<(coord)) ); } + inline bool operator<( const Coord &coord ) { return( x < coord.x && y < coord.y ); } + inline bool operator<=( const Coord &coord ) { return( !(operator>(coord)) ); } + inline Coord &operator+=( const Coord &coord ) { x += coord.x; y += coord.y; return( *this ); } + inline Coord &operator-=( const Coord &coord ) { x -= coord.x; y -= coord.y; return( *this ); } - inline friend Coord operator+( const Coord &coord1, const Coord &coord2 ) { Coord result( coord1 ); result += coord2; return( result ); } - inline friend Coord operator-( const Coord &coord1, const Coord &coord2 ) { Coord result( coord1 ); result -= coord2; return( result ); } + inline friend Coord operator+( const Coord &coord1, const Coord &coord2 ) { Coord result( coord1 ); result += coord2; return( result ); } + inline friend Coord operator-( const Coord &coord1, const Coord &coord2 ) { Coord result( coord1 ); result -= coord2; return( result ); } }; #endif // ZM_COORD_H diff --git a/src/zm_curl_camera.cpp b/src/zm_curl_camera.cpp index da5f7180d..f9b6d0712 100644 --- a/src/zm_curl_camera.cpp +++ b/src/zm_curl_camera.cpp @@ -31,523 +31,523 @@ size_t content_length_match_len; size_t content_type_match_len; cURLCamera::cURLCamera( int p_id, const std::string &p_path, const std::string &p_user, const std::string &p_pass, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), - mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET ) + Camera( p_id, CURL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + mPath( p_path ), mUser( p_user ), mPass ( p_pass ), bTerminate( false ), bReset( false ), mode ( MODE_UNSET ) { - if ( capture ) - { - Initialise(); - } + if ( capture ) + { + Initialise(); + } } cURLCamera::~cURLCamera() { - if ( capture ) - { + if ( capture ) + { - Terminate(); - } + Terminate(); + } } void cURLCamera::Initialise() { - content_length_match_len = strlen(content_length_match); - content_type_match_len = strlen(content_type_match); + content_length_match_len = strlen(content_length_match); + content_type_match_len = strlen(content_type_match); - databuffer.expand(CURL_BUFFER_INITIAL_SIZE); + databuffer.expand(CURL_BUFFER_INITIAL_SIZE); - /* cURL initialization */ - cRet = curl_global_init(CURL_GLOBAL_ALL); - if(cRet != CURLE_OK) { - Fatal("libcurl initialization failed: ", curl_easy_strerror(cRet)); - } + /* cURL initialization */ + cRet = curl_global_init(CURL_GLOBAL_ALL); + if(cRet != CURLE_OK) { + Fatal("libcurl initialization failed: ", curl_easy_strerror(cRet)); + } - Debug(2,"libcurl version: %s",curl_version()); + Debug(2,"libcurl version: %s",curl_version()); - /* Create the shared data mutex */ - nRet = pthread_mutex_init(&shareddata_mutex, NULL); - if(nRet != 0) { - Fatal("Shared data mutex creation failed: %s",strerror(nRet)); - } - /* Create the data available condition variable */ - nRet = pthread_cond_init(&data_available_cond, NULL); - if(nRet != 0) { - Fatal("Data available condition variable creation failed: %s",strerror(nRet)); - } - /* Create the request complete condition variable */ - nRet = pthread_cond_init(&request_complete_cond, NULL); - if(nRet != 0) { - Fatal("Request complete condition variable creation failed: %s",strerror(nRet)); - } + /* Create the shared data mutex */ + nRet = pthread_mutex_init(&shareddata_mutex, NULL); + if(nRet != 0) { + Fatal("Shared data mutex creation failed: %s",strerror(nRet)); + } + /* Create the data available condition variable */ + nRet = pthread_cond_init(&data_available_cond, NULL); + if(nRet != 0) { + Fatal("Data available condition variable creation failed: %s",strerror(nRet)); + } + /* Create the request complete condition variable */ + nRet = pthread_cond_init(&request_complete_cond, NULL); + if(nRet != 0) { + Fatal("Request complete condition variable creation failed: %s",strerror(nRet)); + } - /* Create the thread */ - nRet = pthread_create(&thread, NULL, thread_func_dispatcher, this); - if(nRet != 0) { - Fatal("Thread creation failed: %s",strerror(nRet)); - } + /* Create the thread */ + nRet = pthread_create(&thread, NULL, thread_func_dispatcher, this); + if(nRet != 0) { + Fatal("Thread creation failed: %s",strerror(nRet)); + } } void cURLCamera::Terminate() { - /* Signal the thread to terminate */ - bTerminate = true; + /* Signal the thread to terminate */ + bTerminate = true; - /* Wait for thread termination */ - pthread_join(thread, NULL); + /* Wait for thread termination */ + pthread_join(thread, NULL); - /* Destroy condition variables */ - pthread_cond_destroy(&request_complete_cond); - pthread_cond_destroy(&data_available_cond); + /* Destroy condition variables */ + pthread_cond_destroy(&request_complete_cond); + pthread_cond_destroy(&data_available_cond); - /* Destroy mutex */ - pthread_mutex_destroy(&shareddata_mutex); + /* Destroy mutex */ + pthread_mutex_destroy(&shareddata_mutex); - /* cURL cleanup */ - curl_global_cleanup(); + /* cURL cleanup */ + curl_global_cleanup(); } int cURLCamera::PrimeCapture() { - //Info( "Priming capture from %s", mPath.c_str() ); - return 0; + //Info( "Priming capture from %s", mPath.c_str() ); + return 0; } int cURLCamera::PreCapture() { - // Nothing to do here - return( 0 ); + // Nothing to do here + return( 0 ); } int cURLCamera::Capture( Image &image ) { - bool frameComplete = false; + bool frameComplete = false; - /* MODE_STREAM specific variables */ - bool SubHeadersParsingComplete = false; - unsigned int frame_content_length = 0; - std::string frame_content_type; - bool need_more_data = false; + /* MODE_STREAM specific variables */ + bool SubHeadersParsingComplete = false; + unsigned int frame_content_length = 0; + std::string frame_content_type; + bool need_more_data = false; - /* Grab the mutex to ensure exclusive access to the shared data */ - lock(); + /* Grab the mutex to ensure exclusive access to the shared data */ + lock(); - while (!frameComplete) { + while (!frameComplete) { - /* If the work thread did a reset, reset our local variables */ - if(bReset) { - SubHeadersParsingComplete = false; - frame_content_length = 0; - frame_content_type.clear(); - need_more_data = false; - bReset = false; - } + /* If the work thread did a reset, reset our local variables */ + if(bReset) { + SubHeadersParsingComplete = false; + frame_content_length = 0; + frame_content_type.clear(); + need_more_data = false; + bReset = false; + } - if(mode == MODE_UNSET) { - /* Don't have a mode yet. Sleep while waiting for data */ - nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex); - if(nRet != 0) { - Error("Failed waiting for available data condition variable: %s",strerror(nRet)); - return -20; - } - } + if(mode == MODE_UNSET) { + /* Don't have a mode yet. Sleep while waiting for data */ + nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex); + if(nRet != 0) { + Error("Failed waiting for available data condition variable: %s",strerror(nRet)); + return -20; + } + } - if(mode == MODE_STREAM) { + if(mode == MODE_STREAM) { - /* Subheader parsing */ - while(!SubHeadersParsingComplete && !need_more_data) { + /* Subheader parsing */ + while(!SubHeadersParsingComplete && !need_more_data) { - size_t crlf_start, crlf_end, crlf_size; - std::string subheader; + size_t crlf_start, crlf_end, crlf_size; + std::string subheader; - /* Check if the buffer contains something */ - if(databuffer.empty()) { - /* Empty buffer, wait for data */ - need_more_data = true; - break; - } - - /* Find crlf start */ - crlf_start = memcspn(databuffer,"\r\n",databuffer.size()); - if(crlf_start == databuffer.size()) { - /* Not found, wait for more data */ - need_more_data = true; - break; - } + /* Check if the buffer contains something */ + if(databuffer.empty()) { + /* Empty buffer, wait for data */ + need_more_data = true; + break; + } + + /* Find crlf start */ + crlf_start = memcspn(databuffer,"\r\n",databuffer.size()); + if(crlf_start == databuffer.size()) { + /* Not found, wait for more data */ + need_more_data = true; + break; + } - /* See if we have enough data for determining crlf length */ - if(databuffer.size() < crlf_start+5) { - /* Need more data */ - need_more_data = true; - break; - } + /* See if we have enough data for determining crlf length */ + if(databuffer.size() < crlf_start+5) { + /* Need more data */ + need_more_data = true; + break; + } - /* Find crlf end and calculate crlf size */ - crlf_end = memspn(((const char*)databuffer.head())+crlf_start,"\r\n",5); - crlf_size = (crlf_start + crlf_end) - crlf_start; + /* Find crlf end and calculate crlf size */ + crlf_end = memspn(((const char*)databuffer.head())+crlf_start,"\r\n",5); + crlf_size = (crlf_start + crlf_end) - crlf_start; - /* Is this the end of a previous stream? (This is just before the boundary) */ - if(crlf_start == 0) { - databuffer.consume(crlf_size); - continue; - } + /* Is this the end of a previous stream? (This is just before the boundary) */ + if(crlf_start == 0) { + databuffer.consume(crlf_size); + continue; + } - /* Check for invalid CRLF size */ - if(crlf_size > 4) { - Error("Invalid CRLF length"); - } + /* Check for invalid CRLF size */ + if(crlf_size > 4) { + Error("Invalid CRLF length"); + } - /* Check if the crlf is \n\n or \r\n\r\n (marks end of headers, this is the last header) */ - if( (crlf_size == 2 && memcmp(((const char*)databuffer.head())+crlf_start,"\n\n",2) == 0) || (crlf_size == 4 && memcmp(((const char*)databuffer.head())+crlf_start,"\r\n\r\n",4) == 0) ) { - /* This is the last header */ - SubHeadersParsingComplete = true; - } + /* Check if the crlf is \n\n or \r\n\r\n (marks end of headers, this is the last header) */ + if( (crlf_size == 2 && memcmp(((const char*)databuffer.head())+crlf_start,"\n\n",2) == 0) || (crlf_size == 4 && memcmp(((const char*)databuffer.head())+crlf_start,"\r\n\r\n",4) == 0) ) { + /* This is the last header */ + SubHeadersParsingComplete = true; + } - /* Copy the subheader, excluding the crlf */ - subheader.assign(databuffer, crlf_start); + /* Copy the subheader, excluding the crlf */ + subheader.assign(databuffer, crlf_start); - /* Advance the buffer past this one */ - databuffer.consume(crlf_start+crlf_size); + /* Advance the buffer past this one */ + databuffer.consume(crlf_start+crlf_size); - Debug(7,"Got subheader: %s",subheader.c_str()); + Debug(7,"Got subheader: %s",subheader.c_str()); - /* Find where the data in this header starts */ - size_t subheader_data_start = subheader.rfind(' '); - if(subheader_data_start == std::string::npos) { - subheader_data_start = subheader.find(':'); - } + /* Find where the data in this header starts */ + size_t subheader_data_start = subheader.rfind(' '); + if(subheader_data_start == std::string::npos) { + subheader_data_start = subheader.find(':'); + } - /* Extract the data into a string */ - std::string subheader_data = subheader.substr(subheader_data_start+1, std::string::npos); + /* Extract the data into a string */ + std::string subheader_data = subheader.substr(subheader_data_start+1, std::string::npos); - Debug(8,"Got subheader data: %s",subheader_data.c_str()); + Debug(8,"Got subheader data: %s",subheader_data.c_str()); - /* Check the header */ - if(strncasecmp(subheader.c_str(),content_length_match,content_length_match_len) == 0) { - /* Found the content-length header */ - frame_content_length = atoi(subheader_data.c_str()); - Debug(6,"Got content-length subheader: %d",frame_content_length); - } else if(strncasecmp(subheader.c_str(),content_type_match,content_type_match_len) == 0) { - /* Found the content-type header */ - frame_content_type = subheader_data; - Debug(6,"Got content-type subheader: %s",frame_content_type.c_str()); - } + /* Check the header */ + if(strncasecmp(subheader.c_str(),content_length_match,content_length_match_len) == 0) { + /* Found the content-length header */ + frame_content_length = atoi(subheader_data.c_str()); + Debug(6,"Got content-length subheader: %d",frame_content_length); + } else if(strncasecmp(subheader.c_str(),content_type_match,content_type_match_len) == 0) { + /* Found the content-type header */ + frame_content_type = subheader_data; + Debug(6,"Got content-type subheader: %s",frame_content_type.c_str()); + } - } + } - /* Attempt to extract the frame */ - if(!need_more_data) { - if(!SubHeadersParsingComplete) { - /* We haven't parsed all headers yet */ - need_more_data = true; - } else if(frame_content_length <= 0) { - /* Invalid frame */ - Error("Invalid frame: invalid content length"); - } else if(frame_content_type != "image/jpeg") { - /* Unsupported frame type */ - Error("Unsupported frame: %s",frame_content_type.c_str()); - } else if(frame_content_length > databuffer.size()) { - /* Incomplete frame, wait for more data */ - need_more_data = true; - } else { - /* All good. decode the image */ - image.DecodeJpeg(databuffer.extract(frame_content_length), frame_content_length, colours, subpixelorder); - frameComplete = true; - } - } + /* Attempt to extract the frame */ + if(!need_more_data) { + if(!SubHeadersParsingComplete) { + /* We haven't parsed all headers yet */ + need_more_data = true; + } else if(frame_content_length <= 0) { + /* Invalid frame */ + Error("Invalid frame: invalid content length"); + } else if(frame_content_type != "image/jpeg") { + /* Unsupported frame type */ + Error("Unsupported frame: %s",frame_content_type.c_str()); + } else if(frame_content_length > databuffer.size()) { + /* Incomplete frame, wait for more data */ + need_more_data = true; + } else { + /* All good. decode the image */ + image.DecodeJpeg(databuffer.extract(frame_content_length), frame_content_length, colours, subpixelorder); + frameComplete = true; + } + } - /* Attempt to get more data */ - if(need_more_data) { - nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex); - if(nRet != 0) { - Error("Failed waiting for available data condition variable: %s",strerror(nRet)); - return -18; - } - need_more_data = false; - } + /* Attempt to get more data */ + if(need_more_data) { + nRet = pthread_cond_wait(&data_available_cond,&shareddata_mutex); + if(nRet != 0) { + Error("Failed waiting for available data condition variable: %s",strerror(nRet)); + return -18; + } + need_more_data = false; + } - } else if(mode == MODE_SINGLE) { - /* Check if we have anything */ - if (!single_offsets.empty()) { - if( (single_offsets.front() > 0) && (databuffer.size() >= single_offsets.front()) ) { - /* Extract frame */ - image.DecodeJpeg(databuffer.extract(single_offsets.front()), single_offsets.front(), colours, subpixelorder); - single_offsets.pop_front(); - frameComplete = true; - } else { - /* This shouldn't happen */ - Error("Internal error. Attempting recovery"); - databuffer.consume(single_offsets.front()); - single_offsets.pop_front(); - } - } else { - /* Don't have a frame yet, wait for the request complete condition variable */ - nRet = pthread_cond_wait(&request_complete_cond,&shareddata_mutex); - if(nRet != 0) { - Error("Failed waiting for request complete condition variable: %s",strerror(nRet)); - return -19; - } - } - } else { - /* Failed to match content-type */ - Fatal("Unable to match Content-Type. Check URL, username and password"); - } /* mode */ + } else if(mode == MODE_SINGLE) { + /* Check if we have anything */ + if (!single_offsets.empty()) { + if( (single_offsets.front() > 0) && (databuffer.size() >= single_offsets.front()) ) { + /* Extract frame */ + image.DecodeJpeg(databuffer.extract(single_offsets.front()), single_offsets.front(), colours, subpixelorder); + single_offsets.pop_front(); + frameComplete = true; + } else { + /* This shouldn't happen */ + Error("Internal error. Attempting recovery"); + databuffer.consume(single_offsets.front()); + single_offsets.pop_front(); + } + } else { + /* Don't have a frame yet, wait for the request complete condition variable */ + nRet = pthread_cond_wait(&request_complete_cond,&shareddata_mutex); + if(nRet != 0) { + Error("Failed waiting for request complete condition variable: %s",strerror(nRet)); + return -19; + } + } + } else { + /* Failed to match content-type */ + Fatal("Unable to match Content-Type. Check URL, username and password"); + } /* mode */ - } /* frameComplete loop */ + } /* frameComplete loop */ - /* Release the mutex */ - unlock(); + /* Release the mutex */ + unlock(); - if(!frameComplete) - return -1; + if(!frameComplete) + return -1; - return 0; + return 0; } int cURLCamera::PostCapture() { - // Nothing to do here - return( 0 ); + // Nothing to do here + return( 0 ); } size_t cURLCamera::data_callback(void *buffer, size_t size, size_t nmemb, void *userdata) { - lock(); + lock(); - /* Append the data we just received to our buffer */ - databuffer.append((const char*)buffer, size*nmemb); + /* Append the data we just received to our buffer */ + databuffer.append((const char*)buffer, size*nmemb); - /* Signal data available */ - nRet = pthread_cond_signal(&data_available_cond); - if(nRet != 0) { - Error("Failed signaling data available condition variable: %s",strerror(nRet)); - return -16; - } + /* Signal data available */ + nRet = pthread_cond_signal(&data_available_cond); + if(nRet != 0) { + Error("Failed signaling data available condition variable: %s",strerror(nRet)); + return -16; + } - unlock(); + unlock(); - /* Return bytes processed */ - return size*nmemb; + /* Return bytes processed */ + return size*nmemb; } size_t cURLCamera::header_callback( void *buffer, size_t size, size_t nmemb, void *userdata) { - std::string header; - header.assign((const char*)buffer, size*nmemb); - - Debug(4,"Got header: %s",header.c_str()); + std::string header; + header.assign((const char*)buffer, size*nmemb); + + Debug(4,"Got header: %s",header.c_str()); - /* Check Content-Type header */ - if(strncasecmp(header.c_str(),content_type_match,content_type_match_len) == 0) { - size_t pos = header.find(';'); - if(pos != std::string::npos) { - header.erase(pos, std::string::npos); - } + /* Check Content-Type header */ + if(strncasecmp(header.c_str(),content_type_match,content_type_match_len) == 0) { + size_t pos = header.find(';'); + if(pos != std::string::npos) { + header.erase(pos, std::string::npos); + } - pos = header.rfind(' '); - if(pos == std::string::npos) { - pos = header.find(':'); - } + pos = header.rfind(' '); + if(pos == std::string::npos) { + pos = header.find(':'); + } - std::string content_type = header.substr(pos+1, std::string::npos); - Debug(6,"Content-Type is: %s",content_type.c_str()); + std::string content_type = header.substr(pos+1, std::string::npos); + Debug(6,"Content-Type is: %s",content_type.c_str()); - lock(); + lock(); - const char* multipart_match = "multipart/x-mixed-replace"; - const char* image_jpeg_match = "image/jpeg"; - if(strncasecmp(content_type.c_str(),multipart_match,strlen(multipart_match)) == 0) { - Debug(7,"Content type matched as multipart/x-mixed-replace"); - mode = MODE_STREAM; - } else if(strncasecmp(content_type.c_str(),image_jpeg_match,strlen(image_jpeg_match)) == 0) { - Debug(7,"Content type matched as image/jpeg"); - mode = MODE_SINGLE; - } + const char* multipart_match = "multipart/x-mixed-replace"; + const char* image_jpeg_match = "image/jpeg"; + if(strncasecmp(content_type.c_str(),multipart_match,strlen(multipart_match)) == 0) { + Debug(7,"Content type matched as multipart/x-mixed-replace"); + mode = MODE_STREAM; + } else if(strncasecmp(content_type.c_str(),image_jpeg_match,strlen(image_jpeg_match)) == 0) { + Debug(7,"Content type matched as image/jpeg"); + mode = MODE_SINGLE; + } - unlock(); - } - - /* Return bytes processed */ - return size*nmemb; + unlock(); + } + + /* Return bytes processed */ + return size*nmemb; } void* cURLCamera::thread_func() { - long tRet; - double dSize; + long tRet; + double dSize; - c = curl_easy_init(); - if(c == NULL) { - Fatal("Failed getting easy handle from libcurl"); - } + c = curl_easy_init(); + if(c == NULL) { + Fatal("Failed getting easy handle from libcurl"); + } - /* Set URL */ - cRet = curl_easy_setopt(c, CURLOPT_URL, mPath.c_str()); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl URL: %s", curl_easy_strerror(cRet)); - - /* Header callback */ - cRet = curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, &header_callback_dispatcher); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl header callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_HEADERDATA, this); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl header callback object: %s", curl_easy_strerror(cRet)); + /* Set URL */ + cRet = curl_easy_setopt(c, CURLOPT_URL, mPath.c_str()); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl URL: %s", curl_easy_strerror(cRet)); + + /* Header callback */ + cRet = curl_easy_setopt(c, CURLOPT_HEADERFUNCTION, &header_callback_dispatcher); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl header callback function: %s", curl_easy_strerror(cRet)); + cRet = curl_easy_setopt(c, CURLOPT_HEADERDATA, this); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl header callback object: %s", curl_easy_strerror(cRet)); - /* Data callback */ - cRet = curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, &data_callback_dispatcher); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl data callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_WRITEDATA, this); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl data callback object: %s", curl_easy_strerror(cRet)); + /* Data callback */ + cRet = curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, &data_callback_dispatcher); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl data callback function: %s", curl_easy_strerror(cRet)); + cRet = curl_easy_setopt(c, CURLOPT_WRITEDATA, this); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl data callback object: %s", curl_easy_strerror(cRet)); - /* Progress callback */ - cRet = curl_easy_setopt(c, CURLOPT_NOPROGRESS, 0); - if(cRet != CURLE_OK) - Fatal("Failed enabling libcurl progress callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_PROGRESSFUNCTION, &progress_callback_dispatcher); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl progress callback function: %s", curl_easy_strerror(cRet)); - cRet = curl_easy_setopt(c, CURLOPT_PROGRESSDATA, this); - if(cRet != CURLE_OK) - Fatal("Failed setting libcurl progress callback object: %s", curl_easy_strerror(cRet)); + /* Progress callback */ + cRet = curl_easy_setopt(c, CURLOPT_NOPROGRESS, 0); + if(cRet != CURLE_OK) + Fatal("Failed enabling libcurl progress callback function: %s", curl_easy_strerror(cRet)); + cRet = curl_easy_setopt(c, CURLOPT_PROGRESSFUNCTION, &progress_callback_dispatcher); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl progress callback function: %s", curl_easy_strerror(cRet)); + cRet = curl_easy_setopt(c, CURLOPT_PROGRESSDATA, this); + if(cRet != CURLE_OK) + Fatal("Failed setting libcurl progress callback object: %s", curl_easy_strerror(cRet)); - /* Set username and password */ - if(!mUser.empty()) { - cRet = curl_easy_setopt(c, CURLOPT_USERNAME, mUser.c_str()); - if(cRet != CURLE_OK) - Error("Failed setting username: %s", curl_easy_strerror(cRet)); - } - if(!mPass.empty()) { - cRet = curl_easy_setopt(c, CURLOPT_PASSWORD, mPass.c_str()); - if(cRet != CURLE_OK) - Error("Failed setting password: %s", curl_easy_strerror(cRet)); - } + /* Set username and password */ + if(!mUser.empty()) { + cRet = curl_easy_setopt(c, CURLOPT_USERNAME, mUser.c_str()); + if(cRet != CURLE_OK) + Error("Failed setting username: %s", curl_easy_strerror(cRet)); + } + if(!mPass.empty()) { + cRet = curl_easy_setopt(c, CURLOPT_PASSWORD, mPass.c_str()); + if(cRet != CURLE_OK) + Error("Failed setting password: %s", curl_easy_strerror(cRet)); + } - /* Authenication preference */ - cRet = curl_easy_setopt(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - if(cRet != CURLE_OK) - Warning("Failed setting libcurl acceptable http authenication methods: %s", curl_easy_strerror(cRet)); + /* Authenication preference */ + cRet = curl_easy_setopt(c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + if(cRet != CURLE_OK) + Warning("Failed setting libcurl acceptable http authenication methods: %s", curl_easy_strerror(cRet)); - /* Work loop */ - for(int attempt=1;attempt<=CURL_MAXRETRY;attempt++) { - tRet = 0; - while(!bTerminate) { - /* Do the work */ - cRet = curl_easy_perform(c); + /* Work loop */ + for(int attempt=1;attempt<=CURL_MAXRETRY;attempt++) { + tRet = 0; + while(!bTerminate) { + /* Do the work */ + cRet = curl_easy_perform(c); - if(mode == MODE_SINGLE) { - if(cRet != CURLE_OK) { - break; - } - /* Attempt to get the size of the file */ - cRet = curl_easy_getinfo(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize); - if(cRet != CURLE_OK) { - break; - } - /* We need to lock for the offsets array and the condition variable */ - lock(); - /* Push the size into our offsets array */ - if(dSize > 0) { - single_offsets.push_back(dSize); - } else { - Fatal("Unable to get the size of the image"); - } - /* Signal the request complete condition variable */ - tRet = pthread_cond_signal(&request_complete_cond); - if(tRet != 0) { - Error("Failed signaling request completed condition variable: %s",strerror(tRet)); - } - /* Unlock */ - unlock(); + if(mode == MODE_SINGLE) { + if(cRet != CURLE_OK) { + break; + } + /* Attempt to get the size of the file */ + cRet = curl_easy_getinfo(c, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dSize); + if(cRet != CURLE_OK) { + break; + } + /* We need to lock for the offsets array and the condition variable */ + lock(); + /* Push the size into our offsets array */ + if(dSize > 0) { + single_offsets.push_back(dSize); + } else { + Fatal("Unable to get the size of the image"); + } + /* Signal the request complete condition variable */ + tRet = pthread_cond_signal(&request_complete_cond); + if(tRet != 0) { + Error("Failed signaling request completed condition variable: %s",strerror(tRet)); + } + /* Unlock */ + unlock(); - } else if (mode == MODE_STREAM) { - break; - } - } + } else if (mode == MODE_STREAM) { + break; + } + } - /* Return value checking */ - if(cRet == CURLE_ABORTED_BY_CALLBACK || bTerminate) { - /* Aborted */ - break; - } else if (cRet != CURLE_OK) { - /* Some error */ - Error("cURL Request failed: %s",curl_easy_strerror(cRet)); - if(attempt < CURL_MAXRETRY) { - Error("Retrying.. Attempt %d of %d",attempt,CURL_MAXRETRY); - /* Do a reset */ - lock(); - databuffer.clear(); - single_offsets.clear(); - mode = MODE_UNSET; - bReset = true; - unlock(); - } - tRet = -50; - } - } - - /* Cleanup */ - curl_easy_cleanup(c); - c = NULL; - - return (void*)tRet; + /* Return value checking */ + if(cRet == CURLE_ABORTED_BY_CALLBACK || bTerminate) { + /* Aborted */ + break; + } else if (cRet != CURLE_OK) { + /* Some error */ + Error("cURL Request failed: %s",curl_easy_strerror(cRet)); + if(attempt < CURL_MAXRETRY) { + Error("Retrying.. Attempt %d of %d",attempt,CURL_MAXRETRY); + /* Do a reset */ + lock(); + databuffer.clear(); + single_offsets.clear(); + mode = MODE_UNSET; + bReset = true; + unlock(); + } + tRet = -50; + } + } + + /* Cleanup */ + curl_easy_cleanup(c); + c = NULL; + + return (void*)tRet; } int cURLCamera::lock() { - int nRet; + int nRet; - /* Lock shared data */ - nRet = pthread_mutex_lock(&shareddata_mutex); - if(nRet != 0) { - Error("Failed locking shared data mutex: %s",strerror(nRet)); - } - return nRet; + /* Lock shared data */ + nRet = pthread_mutex_lock(&shareddata_mutex); + if(nRet != 0) { + Error("Failed locking shared data mutex: %s",strerror(nRet)); + } + return nRet; } int cURLCamera::unlock() { - int nRet; + int nRet; - /* Unlock shared data */ - nRet = pthread_mutex_unlock(&shareddata_mutex); - if(nRet != 0) { - Error("Failed unlocking shared data mutex: %s",strerror(nRet)); - } - return nRet; + /* Unlock shared data */ + nRet = pthread_mutex_unlock(&shareddata_mutex); + if(nRet != 0) { + Error("Failed unlocking shared data mutex: %s",strerror(nRet)); + } + return nRet; } int cURLCamera::progress_callback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) { - /* Signal the curl thread to terminate */ - if(bTerminate) - return -10; - - return 0; + /* Signal the curl thread to terminate */ + if(bTerminate) + return -10; + + return 0; } /* These functions call the functions in the class for the correct object */ size_t data_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) { - return ((cURLCamera*)userdata)->data_callback(buffer,size,nmemb,userdata); + return ((cURLCamera*)userdata)->data_callback(buffer,size,nmemb,userdata); } size_t header_callback_dispatcher(void *buffer, size_t size, size_t nmemb, void *userdata) { - return ((cURLCamera*)userdata)->header_callback(buffer,size,nmemb,userdata); + return ((cURLCamera*)userdata)->header_callback(buffer,size,nmemb,userdata); } int progress_callback_dispatcher(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow) { - return ((cURLCamera*)userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow); + return ((cURLCamera*)userdata)->progress_callback(userdata,dltotal,dlnow,ultotal,ulnow); } void* thread_func_dispatcher(void* object) { - return ((cURLCamera*)object)->thread_func(); + return ((cURLCamera*)object)->thread_func(); } diff --git a/src/zm_curl_camera.h b/src/zm_curl_camera.h index dff2e3e52..f7c3540fe 100644 --- a/src/zm_curl_camera.h +++ b/src/zm_curl_camera.h @@ -42,55 +42,55 @@ class cURLCamera : public Camera { protected: - typedef enum {MODE_UNSET, MODE_SINGLE, MODE_STREAM} mode_t; + typedef enum {MODE_UNSET, MODE_SINGLE, MODE_STREAM} mode_t; - std::string mPath; - std::string mUser; - std::string mPass; + std::string mPath; + std::string mUser; + std::string mPass; - /* cURL object(s) */ - CURL* c; + /* cURL object(s) */ + CURL* c; - /* Shared data */ - volatile bool bTerminate; - volatile bool bReset; - volatile mode_t mode; - Buffer databuffer; - std::deque single_offsets; + /* Shared data */ + volatile bool bTerminate; + volatile bool bReset; + volatile mode_t mode; + Buffer databuffer; + std::deque single_offsets; - /* pthread objects */ - pthread_t thread; - pthread_mutex_t shareddata_mutex; - pthread_cond_t data_available_cond; - pthread_cond_t request_complete_cond; + /* pthread objects */ + pthread_t thread; + pthread_mutex_t shareddata_mutex; + pthread_cond_t data_available_cond; + pthread_cond_t request_complete_cond; public: - cURLCamera( int p_id, const std::string &path, const std::string &username, const std::string &password, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - ~cURLCamera(); + cURLCamera( int p_id, const std::string &path, const std::string &username, const std::string &password, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~cURLCamera(); - const std::string &Path() const { return( mPath ); } - const std::string &Username() const { return( mUser ); } - const std::string &Password() const { return( mPass ); } + const std::string &Path() const { return( mPath ); } + const std::string &Username() const { return( mUser ); } + const std::string &Password() const { return( mPass ); } - void Initialise(); - void Terminate(); + void Initialise(); + void Terminate(); - int PrimeCapture(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); - size_t data_callback(void *buffer, size_t size, size_t nmemb, void *userdata); - size_t header_callback(void *buffer, size_t size, size_t nmemb, void *userdata); - int progress_callback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow); - int debug_callback(CURL* handle, curl_infotype type, char* str, size_t strsize, void* data); - void* thread_func(); - int lock(); - int unlock(); + size_t data_callback(void *buffer, size_t size, size_t nmemb, void *userdata); + size_t header_callback(void *buffer, size_t size, size_t nmemb, void *userdata); + int progress_callback(void *userdata, double dltotal, double dlnow, double ultotal, double ulnow); + int debug_callback(CURL* handle, curl_infotype type, char* str, size_t strsize, void* data); + void* thread_func(); + int lock(); + int unlock(); private: - int nRet; - CURLcode cRet; + int nRet; + CURLcode cRet; }; diff --git a/src/zm_db.cpp b/src/zm_db.cpp index a342ca14b..8f2527fc2 100644 --- a/src/zm_db.cpp +++ b/src/zm_db.cpp @@ -29,85 +29,85 @@ int zmDbConnected = false; void zmDbConnect() { - if ( !mysql_init( &dbconn ) ) - { - Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - my_bool reconnect = 1; - if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) ) - Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) ); - std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":/" ); - if ( colonIndex != std::string::npos ) + if ( !mysql_init( &dbconn ) ) + { + Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + my_bool reconnect = 1; + if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) ) + Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) ); + std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":/" ); + if ( colonIndex != std::string::npos ) + { + std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); + std::string dbPort = staticConfig.DB_HOST.substr( colonIndex+1 ); + if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, atoi(dbPort.c_str()), 0, 0 ) ) { - std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); - std::string dbPort = staticConfig.DB_HOST.substr( colonIndex+1 ); - if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, atoi(dbPort.c_str()), 0, 0 ) ) - { - Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); } - else + } + else + { + if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, 0, 0, 0 ) ) { - if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, 0, 0, 0 ) ) - { - Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); } - if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) ) - { - Error( "Can't select database: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - zmDbConnected = true; + } + if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) ) + { + Error( "Can't select database: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + zmDbConnected = true; } void zmDbClose() { - if ( zmDbConnected ) - { - mysql_close( &dbconn ); - // mysql_init() call implicitly mysql_library_init() but - // mysql_close() does not call mysql_library_end() - mysql_library_end(); - zmDbConnected = false; - } + if ( zmDbConnected ) + { + mysql_close( &dbconn ); + // mysql_init() call implicitly mysql_library_init() but + // mysql_close() does not call mysql_library_end() + mysql_library_end(); + zmDbConnected = false; + } } MYSQL_RES * zmDbFetch( const char * query ) { - if ( ! zmDbConnected ) { - Error( "Not connected." ); - return NULL; - } + if ( ! zmDbConnected ) { + Error( "Not connected." ); + return NULL; + } - if ( mysql_query( &dbconn, query ) ) { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - return NULL; - } - Debug( 4, "Success running query: %s", query ); - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) { - Error( "Can't use query result: %s for query %s", mysql_error( &dbconn ), query ); - return NULL; - } - return result; + if ( mysql_query( &dbconn, query ) ) { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + return NULL; + } + Debug( 4, "Success running query: %s", query ); + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) { + Error( "Can't use query result: %s for query %s", mysql_error( &dbconn ), query ); + return NULL; + } + return result; } // end MYSQL_RES * zmDbFetch( const char * query ); MYSQL_ROW zmDbFetchOne( const char *query ) { - MYSQL_RES *result = zmDbFetch( query ); - int n_rows = mysql_num_rows( result ); - if ( n_rows != 1 ) { - Error( "Bogus number of lines return from query, %d returned for query %s.", n_rows, query ); - return NULL; - } + MYSQL_RES *result = zmDbFetch( query ); + int n_rows = mysql_num_rows( result ); + if ( n_rows != 1 ) { + Error( "Bogus number of lines return from query, %d returned for query %s.", n_rows, query ); + return NULL; + } - MYSQL_ROW dbrow = mysql_fetch_row( result ); - mysql_free_result( result ); - if ( ! dbrow ) { - Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) ); - return NULL; - } - return dbrow; + MYSQL_ROW dbrow = mysql_fetch_row( result ); + mysql_free_result( result ); + if ( ! dbrow ) { + Error("Error getting row from query %s. Error is %s", query, mysql_error( &dbconn ) ); + return NULL; + } + return dbrow; } diff --git a/src/zm_event.cpp b/src/zm_event.cpp index 89973d1e4..3fe6a52ae 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -59,500 +59,458 @@ int Event::pre_alarm_count = 0; Event::PreAlarmData Event::pre_alarm_data[MAX_PRE_ALARM_FRAMES] = { { 0 } }; Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap ) : - monitor( p_monitor ), - start_time( p_start_time ), - cause( p_cause ), - noteSetMap( p_noteSetMap ) + monitor( p_monitor ), + start_time( p_start_time ), + cause( p_cause ), + noteSetMap( p_noteSetMap ) { - if ( !initialised ) - Initialise(); + if ( !initialised ) + Initialise(); - std::string notes; - createNotes( notes ); + std::string notes; + createNotes( notes ); - bool untimedEvent = false; - if ( !start_time.tv_sec ) + bool untimedEvent = false; + if ( !start_time.tv_sec ) + { + untimedEvent = true; + gettimeofday( &start_time, 0 ); + } + + static char sql[ZM_SQL_MED_BUFSIZ]; + + struct tm *stime = localtime( &start_time.tv_sec ); + snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s' )", monitor->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str() ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + id = mysql_insert_id( &dbconn ); + if ( untimedEvent ) + { + Warning( "Event %d has zero time, setting to current", id ); + } + end_time.tv_sec = 0; + frames = 0; + alarm_frames = 0; + tot_score = 0; + max_score = 0; + + if ( config.use_deep_storage ) + { + char *path_ptr = path; + path_ptr += snprintf( path_ptr, sizeof(path), "%s/%d", config.dir_events, monitor->Id() ); + + int dt_parts[6]; + dt_parts[0] = stime->tm_year-100; + dt_parts[1] = stime->tm_mon+1; + dt_parts[2] = stime->tm_mday; + dt_parts[3] = stime->tm_hour; + dt_parts[4] = stime->tm_min; + dt_parts[5] = stime->tm_sec; + + char date_path[PATH_MAX] = ""; + char time_path[PATH_MAX] = ""; + char *time_path_ptr = time_path; + for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ ) { - untimedEvent = true; - gettimeofday( &start_time, 0 ); - } + path_ptr += snprintf( path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i] ); - static char sql[ZM_SQL_MED_BUFSIZ]; - - struct tm *stime = localtime( &start_time.tv_sec ); - snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s' )", monitor->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str() ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't insert event: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - id = mysql_insert_id( &dbconn ); - if ( untimedEvent ) - { - Warning( "Event %d has zero time, setting to current", id ); - } - end_time.tv_sec = 0; - frames = 0; - alarm_frames = 0; - tot_score = 0; - max_score = 0; - - if ( config.use_deep_storage ) - { - char *path_ptr = path; - path_ptr += snprintf( path_ptr, sizeof(path), "%s/%d", config.dir_events, monitor->Id() ); - - int dt_parts[6]; - dt_parts[0] = stime->tm_year-100; - dt_parts[1] = stime->tm_mon+1; - dt_parts[2] = stime->tm_mday; - dt_parts[3] = stime->tm_hour; - dt_parts[4] = stime->tm_min; - dt_parts[5] = stime->tm_sec; - - char date_path[PATH_MAX] = ""; - char time_path[PATH_MAX] = ""; - char *time_path_ptr = time_path; - for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ ) - { - path_ptr += snprintf( path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i] ); - - struct stat statbuf; - errno = 0; - if ( stat( path, &statbuf ) ) { - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Fatal( "Can't mkdir %s: %s", path, strerror(errno)); - } - } else { - Warning( "Error stat'ing %s, may be fatal. error is %s", path, strerror(errno)); - } - } - if ( i == 2 ) - strncpy( date_path, path, sizeof(date_path) ); - else if ( i >= 3 ) - time_path_ptr += snprintf( time_path_ptr, sizeof(time_path)-(time_path_ptr-time_path), "%s%02d", i>3?"/":"", dt_parts[i] ); - } - char id_file[PATH_MAX]; - // Create event id symlink - snprintf( id_file, sizeof(id_file), "%s/.%d", date_path, id ); - if ( symlink( time_path, id_file ) < 0 ) - Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno)); - // Create empty id tag file - snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); - if ( FILE *id_fp = fopen( id_file, "w" ) ) - fclose( id_fp ); - else - Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); - } - else - { - snprintf( path, sizeof(path), "%s/%d/%d", config.dir_events, monitor->Id(), id ); - - struct stat statbuf; - errno = 0; - stat( path, &statbuf ); + struct stat statbuf; + errno = 0; + if ( stat( path, &statbuf ) ) { if ( errno == ENOENT || errno == ENOTDIR ) { - if ( mkdir( path, 0755 ) ) - { - Error( "Can't mkdir %s: %s", path, strerror(errno)); - } + if ( mkdir( path, 0755 ) ) + { + Fatal( "Can't mkdir %s: %s", path, strerror(errno)); + } + } else { + Warning( "Error stat'ing %s, may be fatal. error is %s", path, strerror(errno)); } - char id_file[PATH_MAX]; - // Create empty id tag file - snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); - if ( FILE *id_fp = fopen( id_file, "w" ) ) - fclose( id_fp ); - else - Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); + } + if ( i == 2 ) + strncpy( date_path, path, sizeof(date_path) ); + else if ( i >= 3 ) + time_path_ptr += snprintf( time_path_ptr, sizeof(time_path)-(time_path_ptr-time_path), "%s%02d", i>3?"/":"", dt_parts[i] ); } - last_db_frame = 0; + char id_file[PATH_MAX]; + // Create event id symlink + snprintf( id_file, sizeof(id_file), "%s/.%d", date_path, id ); + if ( symlink( time_path, id_file ) < 0 ) + Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno)); + // Create empty id tag file + snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); + if ( FILE *id_fp = fopen( id_file, "w" ) ) + fclose( id_fp ); + else + Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); + } + else + { + snprintf( path, sizeof(path), "%s/%d/%d", config.dir_events, monitor->Id(), id ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't mkdir %s: %s", path, strerror(errno)); + } + } + char id_file[PATH_MAX]; + // Create empty id tag file + snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); + if ( FILE *id_fp = fopen( id_file, "w" ) ) + fclose( id_fp ); + else + Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); + } + last_db_frame = 0; } Event::~Event() { - if ( frames > last_db_frame ) - { - struct DeltaTimeval delta_time; - DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 ); - - Debug( 1, "Adding closing frame %d to DB", frames ); - static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - } - - static char sql[ZM_SQL_MED_BUFSIZ]; - + if ( frames > last_db_frame ) + { struct DeltaTimeval delta_time; DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 ); - snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id ); + Debug( 1, "Adding closing frame %d to DB", frames ); + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); if ( mysql_query( &dbconn, sql ) ) { - Error( "Can't update event: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); + Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); } + } + + static char sql[ZM_SQL_MED_BUFSIZ]; + + struct DeltaTimeval delta_time; + DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 ); + + snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't update event: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } void Event::createNotes( std::string ¬es ) { - notes.clear(); - for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) + notes.clear(); + for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) + { + notes += mapIter->first; + notes += ": "; + const StringSet &stringSet = mapIter->second; + for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) { - notes += mapIter->first; - notes += ": "; - const StringSet &stringSet = mapIter->second; - for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) - { - if ( setIter != stringSet.begin() ) - notes += ", "; - notes += *setIter; - } + if ( setIter != stringSet.begin() ) + notes += ", "; + notes += *setIter; } + } } int Event::sd = -1; bool Event::OpenFrameSocket( int monitor_id ) { - if ( sd > 0 ) + if ( sd > 0 ) + { + close( sd ); + } + + sd = socket( AF_UNIX, SOCK_STREAM, 0); + if ( sd < 0 ) + { + Error( "Can't create socket: %s", strerror(errno) ); + return( false ); + } + + int socket_buffer_size = config.frame_socket_size; + if ( socket_buffer_size > 0 ) + { + if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 ) { - close( sd ); + Error( "Can't get socket buffer size to %d, error = %s", socket_buffer_size, strerror(errno) ); + close( sd ); + sd = -1; + return( false ); } + } - sd = socket( AF_UNIX, SOCK_STREAM, 0); - if ( sd < 0 ) - { - Error( "Can't create socket: %s", strerror(errno) ); - return( false ); - } + int flags; + if ( (flags = fcntl( sd, F_GETFL )) < 0 ) + { + Error( "Can't get socket flags, error = %s", strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } + flags |= O_NONBLOCK; + if ( fcntl( sd, F_SETFL, flags ) < 0 ) + { + Error( "Can't set socket flags, error = %s", strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } - int socket_buffer_size = config.frame_socket_size; - if ( socket_buffer_size > 0 ) - { - if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 ) - { - Error( "Can't get socket buffer size to %d, error = %s", socket_buffer_size, strerror(errno) ); - close( sd ); - sd = -1; - return( false ); - } - } + char sock_path[PATH_MAX] = ""; + snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id ); - int flags; - if ( (flags = fcntl( sd, F_GETFL )) < 0 ) - { - Error( "Can't get socket flags, error = %s", strerror(errno) ); - close( sd ); - sd = -1; - return( false ); - } - flags |= O_NONBLOCK; - if ( fcntl( sd, F_SETFL, flags ) < 0 ) - { - Error( "Can't set socket flags, error = %s", strerror(errno) ); - close( sd ); - sd = -1; - return( false ); - } + struct sockaddr_un addr; - char sock_path[PATH_MAX] = ""; - snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id ); + strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) ); + addr.sun_family = AF_UNIX; - struct sockaddr_un addr; + if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 ) + { + Warning( "Can't connect to frame server: %s", strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } - strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) ); - addr.sun_family = AF_UNIX; - - if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 ) - { - Warning( "Can't connect to frame server: %s", strerror(errno) ); - close( sd ); - sd = -1; - return( false ); - } - - Debug( 1, "Opened connection to frame server" ); - return( true ); + Debug( 1, "Opened connection to frame server" ); + return( true ); } bool Event::ValidateFrameSocket( int monitor_id ) { - if ( sd < 0 ) - { - return( OpenFrameSocket( monitor_id ) ); - } - return( true ); + if ( sd < 0 ) + { + return( OpenFrameSocket( monitor_id ) ); + } + return( true ); } bool Event::SendFrameImage( const Image *image, bool alarm_frame ) { - if ( !ValidateFrameSocket( monitor->Id() ) ) + if ( !ValidateFrameSocket( monitor->Id() ) ) + { + return( false ); + } + + static int jpg_buffer_size = 0; + static unsigned char jpg_buffer[ZM_MAX_IMAGE_SIZE]; + + image->EncodeJpeg( jpg_buffer, &jpg_buffer_size, (alarm_frame&&(config.jpeg_alarm_file_quality>config.jpeg_file_quality))?config.jpeg_alarm_file_quality:config.jpeg_file_quality ); + + static FrameHeader frame_header; + + frame_header.event_id = id; + if ( config.use_deep_storage ) + frame_header.event_time = start_time.tv_sec; + frame_header.frame_id = frames; + frame_header.alarm_frame = alarm_frame; + frame_header.image_length = jpg_buffer_size; + + struct iovec iovecs[2]; + iovecs[0].iov_base = &frame_header; + iovecs[0].iov_len = sizeof(frame_header); + iovecs[1].iov_base = jpg_buffer; + iovecs[1].iov_len = jpg_buffer_size; + + ssize_t writev_size = sizeof(frame_header)+jpg_buffer_size; + ssize_t writev_result = writev( sd, iovecs, sizeof(iovecs)/sizeof(*iovecs)); + if ( writev_result != writev_size ) + { + if ( writev_result < 0 ) { - return( false ); + if ( errno == EAGAIN ) + { + Warning( "Blocking write detected" ); + } + else + { + Error( "Can't write frame: %s", strerror(errno) ); + close( sd ); + sd = -1; + } } - - static int jpg_buffer_size = 0; - static unsigned char jpg_buffer[ZM_MAX_IMAGE_SIZE]; - - image->EncodeJpeg( jpg_buffer, &jpg_buffer_size, (alarm_frame&&(config.jpeg_alarm_file_quality>config.jpeg_file_quality))?config.jpeg_alarm_file_quality:config.jpeg_file_quality ); - - static FrameHeader frame_header; - - frame_header.event_id = id; - if ( config.use_deep_storage ) - frame_header.event_time = start_time.tv_sec; - frame_header.frame_id = frames; - frame_header.alarm_frame = alarm_frame; - frame_header.image_length = jpg_buffer_size; - - struct iovec iovecs[2]; - iovecs[0].iov_base = &frame_header; - iovecs[0].iov_len = sizeof(frame_header); - iovecs[1].iov_base = jpg_buffer; - iovecs[1].iov_len = jpg_buffer_size; - - ssize_t writev_size = sizeof(frame_header)+jpg_buffer_size; - ssize_t writev_result = writev( sd, iovecs, sizeof(iovecs)/sizeof(*iovecs)); - if ( writev_result != writev_size ) + else { - if ( writev_result < 0 ) - { - if ( errno == EAGAIN ) - { - Warning( "Blocking write detected" ); - } - else - { - Error( "Can't write frame: %s", strerror(errno) ); - close( sd ); - sd = -1; - } - } - else - { - Error( "Incomplete frame write: %zd of %zd bytes written", writev_result, writev_size ); - close( sd ); - sd = -1; - } - return( false ); + Error( "Incomplete frame write: %zd of %zd bytes written", writev_result, writev_size ); + close( sd ); + sd = -1; } - Debug( 1, "Wrote frame image, %d bytes", jpg_buffer_size ); + return( false ); + } + Debug( 1, "Wrote frame image, %d bytes", jpg_buffer_size ); - return( true ); + return( true ); } bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) { - Image* ImgToWrite; - Image* ts_image = NULL; + Image* ImgToWrite; + Image* ts_image = NULL; - if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped. - { - ts_image = new Image(*image); - monitor->TimestampImage( ts_image, ×tamp ); - ImgToWrite=ts_image; - } - else - ImgToWrite=image; + if ( config.timestamp_on_capture ) // stash the image we plan to use in another pointer regardless if timestamped. + { + ts_image = new Image(*image); + monitor->TimestampImage( ts_image, ×tamp ); + ImgToWrite=ts_image; + } + else + ImgToWrite=image; - if ( !config.opt_frame_server || !SendFrameImage(ImgToWrite, alarm_frame) ) - { - int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default - ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write - } - if(ts_image) delete(ts_image); // clean up if used. - return( true ); + if ( !config.opt_frame_server || !SendFrameImage(ImgToWrite, alarm_frame) ) + { + int thisquality = ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) ? config.jpeg_alarm_file_quality : 0 ; // quality to use, zero is default + ImgToWrite->WriteJpeg( event_file, thisquality, (monitor->Exif() ? timestamp : (timeval){0,0}) ); // exif is only timestamp at present this switches on or off for write + } + if(ts_image) delete(ts_image); // clean up if used. + return( true ); } void Event::updateNotes( const StringSetMap &newNoteSetMap ) { - bool update = false; + bool update = false; - //Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() ); - if ( newNoteSetMap.size() > 0 ) + //Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() ); + if ( newNoteSetMap.size() > 0 ) + { + if ( noteSetMap.size() == 0 ) { - if ( noteSetMap.size() == 0 ) + noteSetMap = newNoteSetMap; + update = true; + } + else + { + for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) + { + const std::string &newNoteGroup = newNoteSetMapIter->first; + const StringSet &newNoteSet = newNoteSetMapIter->second; + //Info( "Got %d new strings", newNoteSet.size() ); + if ( newNoteSet.size() > 0 ) { - noteSetMap = newNoteSetMap; + StringSetMap::iterator noteSetMapIter = noteSetMap.find( newNoteGroup ); + if ( noteSetMapIter == noteSetMap.end() ) + { + //Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() ); + noteSetMap.insert( StringSetMap::value_type( newNoteGroup, newNoteSet ) ); update = true; - } - else - { - for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) + } + else + { + StringSet ¬eSet = noteSetMapIter->second; + //Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() ); + for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) { - const std::string &newNoteGroup = newNoteSetMapIter->first; - const StringSet &newNoteSet = newNoteSetMapIter->second; - //Info( "Got %d new strings", newNoteSet.size() ); - if ( newNoteSet.size() > 0 ) - { - StringSetMap::iterator noteSetMapIter = noteSetMap.find( newNoteGroup ); - if ( noteSetMapIter == noteSetMap.end() ) - { - //Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() ); - noteSetMap.insert( StringSetMap::value_type( newNoteGroup, newNoteSet ) ); - update = true; - } - else - { - StringSet ¬eSet = noteSetMapIter->second; - //Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() ); - for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) - { - const std::string &newNote = *newNoteSetIter; - StringSet::iterator noteSetIter = noteSet.find( newNote ); - if ( noteSetIter == noteSet.end() ) - { - noteSet.insert( newNote ); - update = true; - } - } - } - } + const std::string &newNote = *newNoteSetIter; + StringSet::iterator noteSetIter = noteSet.find( newNote ); + if ( noteSetIter == noteSet.end() ) + { + noteSet.insert( newNote ); + update = true; + } } + } } + } } + } - if ( update ) - { - std::string notes; - createNotes( notes ); + if ( update ) + { + std::string notes; + createNotes( notes ); - Debug( 2, "Updating notes for event %d, '%s'", id, notes.c_str() ); - static char sql[ZM_SQL_MED_BUFSIZ]; + Debug( 2, "Updating notes for event %d, '%s'", id, notes.c_str() ); + static char sql[ZM_SQL_MED_BUFSIZ]; #if USE_PREPARED_SQL - static MYSQL_STMT *stmt = 0; + static MYSQL_STMT *stmt = 0; - char notesStr[ZM_SQL_MED_BUFSIZ] = ""; - unsigned long notesLen = 0; + char notesStr[ZM_SQL_MED_BUFSIZ] = ""; + unsigned long notesLen = 0; - if ( !stmt ) - { - const char *sql = "update Events set Notes = ? where Id = ?"; + if ( !stmt ) + { + const char *sql = "update Events set Notes = ? where Id = ?"; - stmt = mysql_stmt_init( &dbconn ); - if ( mysql_stmt_prepare( stmt, sql, strlen(sql) ) ) - { - Fatal( "Unable to prepare sql '%s': %s", sql, mysql_stmt_error(stmt) ); - } + stmt = mysql_stmt_init( &dbconn ); + if ( mysql_stmt_prepare( stmt, sql, strlen(sql) ) ) + { + Fatal( "Unable to prepare sql '%s': %s", sql, mysql_stmt_error(stmt) ); + } - /* Get the parameter count from the statement */ - if ( mysql_stmt_param_count( stmt ) != 2 ) - { - Fatal( "Unexpected parameter count %ld in sql '%s'", mysql_stmt_param_count( stmt ), sql ); - } + /* Get the parameter count from the statement */ + if ( mysql_stmt_param_count( stmt ) != 2 ) + { + Fatal( "Unexpected parameter count %ld in sql '%s'", mysql_stmt_param_count( stmt ), sql ); + } - MYSQL_BIND bind[2]; - memset(bind, 0, sizeof(bind)); + MYSQL_BIND bind[2]; + memset(bind, 0, sizeof(bind)); - /* STRING PARAM */ - bind[0].buffer_type = MYSQL_TYPE_STRING; - bind[0].buffer = (char *)notesStr; - bind[0].buffer_length = sizeof(notesStr); - bind[0].is_null = 0; - bind[0].length = ¬esLen; + /* STRING PARAM */ + bind[0].buffer_type = MYSQL_TYPE_STRING; + bind[0].buffer = (char *)notesStr; + bind[0].buffer_length = sizeof(notesStr); + bind[0].is_null = 0; + bind[0].length = ¬esLen; - bind[1].buffer_type= MYSQL_TYPE_LONG; - bind[1].buffer= (char *)&id; - bind[1].is_null= 0; - bind[1].length= 0; + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= (char *)&id; + bind[1].is_null= 0; + bind[1].length= 0; - /* Bind the buffers */ - if ( mysql_stmt_bind_param( stmt, bind ) ) - { - Fatal( "Unable to bind sql '%s': %s", sql, mysql_stmt_error(stmt) ); - } - } - - strncpy( notesStr, notes.c_str(), sizeof(notesStr) ); - notesLen = notes.length(); - - if ( mysql_stmt_execute( stmt ) ) - { - Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) ); - } -#else - static char escapedNotes[ZM_SQL_MED_BUFSIZ]; - - mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() ); - - snprintf( sql, sizeof(sql), "update Events set Notes = '%s' where Id = %d", escapedNotes, id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't insert event: %s", mysql_error( &dbconn ) ); - } -#endif + /* Bind the buffers */ + if ( mysql_stmt_bind_param( stmt, bind ) ) + { + Fatal( "Unable to bind sql '%s': %s", sql, mysql_stmt_error(stmt) ); + } } + + strncpy( notesStr, notes.c_str(), sizeof(notesStr) ); + notesLen = notes.length(); + + if ( mysql_stmt_execute( stmt ) ) + { + Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) ); + } +#else + static char escapedNotes[ZM_SQL_MED_BUFSIZ]; + + mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() ); + + snprintf( sql, sizeof(sql), "update Events set Notes = '%s' where Id = %d", escapedNotes, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event: %s", mysql_error( &dbconn ) ); + } +#endif + } } void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps ) { - for (int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE) { - AddFramesInternal(n_frames, i, images, timestamps); - } + for (int i = 0; i < n_frames; i += ZM_SQL_BATCH_SIZE) { + AddFramesInternal(n_frames, i, images, timestamps); + } } void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ) { - static char sql[ZM_SQL_LGE_BUFSIZ]; - strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql) ); - int frameCount = 0; - for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ ) + static char sql[ZM_SQL_LGE_BUFSIZ]; + strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql) ); + int frameCount = 0; + for ( int i = start_frame; i < n_frames && i - start_frame < ZM_SQL_BATCH_SIZE; i++ ) + { + if ( !timestamps[i]->tv_sec ) { - if ( !timestamps[i]->tv_sec ) - { - Debug( 1, "Not adding pre-capture frame %d, zero timestamp", i ); - continue; - } - - frames++; - - static char event_file[PATH_MAX]; - snprintf( event_file, sizeof(event_file), capture_file_format, path, frames ); - - Debug( 1, "Writing pre-capture frame %d", frames ); - WriteFrameImage( images[i], *(timestamps[i]), event_file ); - - struct DeltaTimeval delta_time; - DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 ); - - int sql_len = strlen(sql); - snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); - - frameCount++; - } - - if ( frameCount ) - { - Debug( 1, "Adding %d/%d frames to DB", frameCount, n_frames ); - *(sql+strlen(sql)-2) = '\0'; - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't insert frames: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - last_db_frame = frames; - } - else - { - Debug( 1, "No valid pre-capture frames to add" ); - } -} - -void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *alarm_image ) -{ - if ( !timestamp.tv_sec ) - { - Debug( 1, "Not adding new frame, zero timestamp" ); - return; + Debug( 1, "Not adding pre-capture frame %d, zero timestamp", i ); + continue; } frames++; @@ -560,933 +518,975 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image * static char event_file[PATH_MAX]; snprintf( event_file, sizeof(event_file), capture_file_format, path, frames ); - Debug( 1, "Writing capture frame %d", frames ); - WriteFrameImage( image, timestamp, event_file ); + Debug( 1, "Writing pre-capture frame %d", frames ); + WriteFrameImage( images[i], *(timestamps[i]), event_file ); struct DeltaTimeval delta_time; - DELTA_TIMEVAL( delta_time, timestamp, start_time, DT_PREC_2 ); + DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 ); - const char *frame_type = score>0?"Alarm":(score<0?"Bulk":"Normal"); - if ( score < 0 ) - score = 0; + int sql_len = strlen(sql); + snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); - bool db_frame = (strcmp(frame_type,"Bulk") != 0) || ((frames%config.bulk_frame_interval)==0) || !frames; - if ( db_frame ) + frameCount++; + } + + if ( frameCount ) + { + Debug( 1, "Adding %d/%d frames to DB", frameCount, n_frames ); + *(sql+strlen(sql)-2) = '\0'; + if ( mysql_query( &dbconn, sql ) ) { - - Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, frame_type ); - static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type, timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - last_db_frame = frames; - - // We are writing a Bulk frame - if ( !strcmp( frame_type,"Bulk") ) - { - snprintf( sql, sizeof(sql), "update Events set Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't update event: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - } + Error( "Can't insert frames: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); } + last_db_frame = frames; + } + else + { + Debug( 1, "No valid pre-capture frames to add" ); + } +} - end_time = timestamp; +void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *alarm_image ) +{ + if ( !timestamp.tv_sec ) + { + Debug( 1, "Not adding new frame, zero timestamp" ); + return; + } - // We are writing an Alarm frame - if ( !strcmp( frame_type,"Alarm") ) + frames++; + + static char event_file[PATH_MAX]; + snprintf( event_file, sizeof(event_file), capture_file_format, path, frames ); + + Debug( 1, "Writing capture frame %d", frames ); + WriteFrameImage( image, timestamp, event_file ); + + struct DeltaTimeval delta_time; + DELTA_TIMEVAL( delta_time, timestamp, start_time, DT_PREC_2 ); + + const char *frame_type = score>0?"Alarm":(score<0?"Bulk":"Normal"); + if ( score < 0 ) + score = 0; + + bool db_frame = (strcmp(frame_type,"Bulk") != 0) || ((frames%config.bulk_frame_interval)==0) || !frames; + if ( db_frame ) + { + + Debug( 1, "Adding frame %d of type \"%s\" to DB", frames, frame_type ); + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type, timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score ); + if ( mysql_query( &dbconn, sql ) ) { - alarm_frames++; - - tot_score += score; - if ( score > (int)max_score ) - max_score = score; - - if ( alarm_image ) - { - snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames ); - - Debug( 1, "Writing analysis frame %d", frames ); - WriteFrameImage( alarm_image, timestamp, event_file, true ); - } + Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); } - - /* This makes viewing the diagnostic images impossible because it keeps deleting them - if ( config.record_diag_images ) + last_db_frame = frames; + + // We are writing a Bulk frame + if ( !strcmp( frame_type,"Bulk") ) { - char diag_glob[PATH_MAX] = ""; - - snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", config.dir_events, monitor->Id() ); - glob_t pglob; - int glob_status = glob( diag_glob, 0, 0, &pglob ); - if ( glob_status != 0 ) - { - if ( glob_status < 0 ) - { - Error( "Can't glob '%s': %s", diag_glob, strerror(errno) ); - } - else - { - Debug( 1, "Can't glob '%s': %d", diag_glob, glob_status ); - } - } - else - { - char new_diag_path[PATH_MAX] = ""; - for ( int i = 0; i < pglob.gl_pathc; i++ ) - { - char *diag_path = pglob.gl_pathv[i]; - - char *diag_file = strstr( diag_path, "diag-" ); - - if ( diag_file ) - { - snprintf( new_diag_path, sizeof(new_diag_path), general_file_format, path, frames, diag_file ); - - if ( rename( diag_path, new_diag_path ) < 0 ) - { - Error( "Can't rename '%s' to '%s': %s", diag_path, new_diag_path, strerror(errno) ); - } - } - } - } - globfree( &pglob ); + snprintf( sql, sizeof(sql), "update Events set Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't update event: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } - */ + } + + end_time = timestamp; + + // We are writing an Alarm frame + if ( !strcmp( frame_type,"Alarm") ) + { + alarm_frames++; + + tot_score += score; + if ( score > (int)max_score ) + max_score = score; + + if ( alarm_image ) + { + snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames ); + + Debug( 1, "Writing analysis frame %d", frames ); + WriteFrameImage( alarm_image, timestamp, event_file, true ); + } + } + + /* This makes viewing the diagnostic images impossible because it keeps deleting them + if ( config.record_diag_images ) + { + char diag_glob[PATH_MAX] = ""; + + snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", config.dir_events, monitor->Id() ); + glob_t pglob; + int glob_status = glob( diag_glob, 0, 0, &pglob ); + if ( glob_status != 0 ) + { + if ( glob_status < 0 ) + { + Error( "Can't glob '%s': %s", diag_glob, strerror(errno) ); + } + else + { + Debug( 1, "Can't glob '%s': %d", diag_glob, glob_status ); + } + } + else + { + char new_diag_path[PATH_MAX] = ""; + for ( int i = 0; i < pglob.gl_pathc; i++ ) + { + char *diag_path = pglob.gl_pathv[i]; + + char *diag_file = strstr( diag_path, "diag-" ); + + if ( diag_file ) + { + snprintf( new_diag_path, sizeof(new_diag_path), general_file_format, path, frames, diag_file ); + + if ( rename( diag_path, new_diag_path ) < 0 ) + { + Error( "Can't rename '%s' to '%s': %s", diag_path, new_diag_path, strerror(errno) ); + } + } + } + } + globfree( &pglob ); + } + */ } bool EventStream::loadInitialEventData( int monitor_id, time_t event_time ) { - static char sql[ZM_SQL_SML_BUFSIZ]; + static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %d and unix_timestamp( EndTime ) > %ld order by Id asc limit 1", monitor_id, event_time ); + snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %d and unix_timestamp( EndTime ) > %ld order by Id asc limit 1", monitor_id, event_time ); - if ( mysql_query( &dbconn, sql ) ) + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + MYSQL_ROW dbrow = mysql_fetch_row( result ); + + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + int init_event_id = atoi( dbrow[0] ); + + mysql_free_result( result ); + + loadEventData( init_event_id ); + + if ( event_time ) + { + curr_stream_time = event_time; + curr_frame_id = 1; + if ( event_time >= event_data->start_time ) { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - MYSQL_ROW dbrow = mysql_fetch_row( result ); - - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - - int init_event_id = atoi( dbrow[0] ); - - mysql_free_result( result ); - - loadEventData( init_event_id ); - - if ( event_time ) - { - curr_stream_time = event_time; - curr_frame_id = 1; - if ( event_time >= event_data->start_time ) + for (unsigned int i = 0; i < event_data->frame_count; i++ ) + { + //Info( "eft %d > et %d", event_data->frames[i].timestamp, event_time ); + if ( event_data->frames[i].timestamp >= event_time ) { - for (unsigned int i = 0; i < event_data->frame_count; i++ ) - { - //Info( "eft %d > et %d", event_data->frames[i].timestamp, event_time ); - if ( event_data->frames[i].timestamp >= event_time ) - { - curr_frame_id = i+1; - Debug( 3, "Set cst:%.2f", curr_stream_time ); - Debug( 3, "Set cfid:%d", curr_frame_id ); - break; - } - } - Debug( 3, "Skipping %ld frames", event_data->frame_count ); + curr_frame_id = i+1; + Debug( 3, "Set cst:%.2f", curr_stream_time ); + Debug( 3, "Set cfid:%d", curr_frame_id ); + break; } + } + Debug( 3, "Skipping %ld frames", event_data->frame_count ); } - return( true ); + } + return( true ); } bool EventStream::loadInitialEventData( int init_event_id, int init_frame_id ) { - loadEventData( init_event_id ); + loadEventData( init_event_id ); - if ( init_frame_id ) - { - curr_stream_time = event_data->frames[init_frame_id-1].timestamp; - curr_frame_id = init_frame_id; - } - else - { - curr_stream_time = event_data->start_time; - } + if ( init_frame_id ) + { + curr_stream_time = event_data->frames[init_frame_id-1].timestamp; + curr_frame_id = init_frame_id; + } + else + { + curr_stream_time = event_data->start_time; + } - return( true ); + return( true ); } bool EventStream::loadEventData( int event_id ) { - static char sql[ZM_SQL_MED_BUFSIZ]; + static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "select M.Id, M.Name, E.Frames, unix_timestamp( StartTime ) as StartTimestamp, max(F.Delta)-min(F.Delta) as Duration from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where E.Id = %d group by E.Id", event_id ); + snprintf( sql, sizeof(sql), "select M.Id, M.Name, E.Frames, unix_timestamp( StartTime ) as StartTimestamp, max(F.Delta)-min(F.Delta) as Duration from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where E.Id = %d group by E.Id", event_id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - if ( !mysql_num_rows( result ) ) - { - Fatal( "Unable to load event %d, not found in DB", event_id ); - } + if ( !mysql_num_rows( result ) ) + { + Fatal( "Unable to load event %d, not found in DB", event_id ); + } - MYSQL_ROW dbrow = mysql_fetch_row( result ); + MYSQL_ROW dbrow = mysql_fetch_row( result ); - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - delete event_data; - event_data = new EventData; - event_data->event_id = event_id; - event_data->monitor_id = atoi( dbrow[0] ); - event_data->start_time = atoi(dbrow[3]); - if ( config.use_deep_storage ) - { - struct tm *event_time = localtime( &event_data->start_time ); - if ( config.dir_events[0] == '/' ) - snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); - else - snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); - } + delete event_data; + event_data = new EventData; + event_data->event_id = event_id; + event_data->monitor_id = atoi( dbrow[0] ); + event_data->start_time = atoi(dbrow[3]); + if ( config.use_deep_storage ) + { + struct tm *event_time = localtime( &event_data->start_time ); + if ( config.dir_events[0] == '/' ) + snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); else + snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); + } + else + { + if ( config.dir_events[0] == '/' ) + snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", config.dir_events, event_data->monitor_id, event_data->event_id ); + else + snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_data->event_id ); + } + event_data->frame_count = dbrow[2] == NULL ? 0 : atoi(dbrow[2]); + event_data->duration = atof(dbrow[4]); + + updateFrameRate( (double)event_data->frame_count/event_data->duration ); + + mysql_free_result( result ); + + snprintf( sql, sizeof(sql), "select FrameId, unix_timestamp( `TimeStamp` ), Delta from Frames where EventId = %d order by FrameId asc", event_id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + event_data->n_frames = mysql_num_rows( result ); + + event_data->frames = new FrameData[event_data->frame_count]; + int id, last_id = 0; + time_t timestamp, last_timestamp = event_data->start_time; + double delta, last_delta = 0.0; + while ( ( dbrow = mysql_fetch_row( result ) ) ) + { + id = atoi(dbrow[0]); + timestamp = atoi(dbrow[1]); + delta = atof(dbrow[2]); + int id_diff = id - last_id; + double frame_delta = (delta-last_delta)/id_diff; + if ( id_diff > 1 ) { - if ( config.dir_events[0] == '/' ) - snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", config.dir_events, event_data->monitor_id, event_data->event_id ); - else - snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_data->event_id ); + for ( int i = last_id+1; i < id; i++ ) + { + event_data->frames[i-1].timestamp = (time_t)(last_timestamp + ((i-last_id)*frame_delta)); + event_data->frames[i-1].offset = (time_t)(event_data->frames[i-1].timestamp-event_data->start_time); + event_data->frames[i-1].delta = frame_delta; + event_data->frames[i-1].in_db = false; + } } - event_data->frame_count = dbrow[2] == NULL ? 0 : atoi(dbrow[2]); - event_data->duration = atof(dbrow[4]); + event_data->frames[id-1].timestamp = timestamp; + event_data->frames[id-1].offset = (time_t)(event_data->frames[id-1].timestamp-event_data->start_time); + event_data->frames[id-1].delta = id>1?frame_delta:0.0; + event_data->frames[id-1].in_db = true; + last_id = id; + last_delta = delta; + last_timestamp = timestamp; + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - updateFrameRate( (double)event_data->frame_count/event_data->duration ); + //for ( int i = 0; i < 250; i++ ) + //{ + //Info( "%d -> %d @ %f (%d)", i+1, event_data->frames[i].timestamp, event_data->frames[i].delta, event_data->frames[i].in_db ); + //} - mysql_free_result( result ); + mysql_free_result( result ); - snprintf( sql, sizeof(sql), "select FrameId, unix_timestamp( `TimeStamp` ), Delta from Frames where EventId = %d order by FrameId asc", event_id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( forceEventChange || mode == MODE_ALL_GAPLESS ) + { + if ( replay_rate > 0 ) + curr_stream_time = event_data->frames[0].timestamp; + else + curr_stream_time = event_data->frames[event_data->frame_count-1].timestamp; + } + Debug( 2, "Event:%ld, Frames:%ld, Duration: %.2f", event_data->event_id, event_data->frame_count, event_data->duration ); - result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - - event_data->n_frames = mysql_num_rows( result ); - - event_data->frames = new FrameData[event_data->frame_count]; - int id, last_id = 0; - time_t timestamp, last_timestamp = event_data->start_time; - double delta, last_delta = 0.0; - while ( ( dbrow = mysql_fetch_row( result ) ) ) - { - id = atoi(dbrow[0]); - timestamp = atoi(dbrow[1]); - delta = atof(dbrow[2]); - int id_diff = id - last_id; - double frame_delta = (delta-last_delta)/id_diff; - if ( id_diff > 1 ) - { - for ( int i = last_id+1; i < id; i++ ) - { - event_data->frames[i-1].timestamp = (time_t)(last_timestamp + ((i-last_id)*frame_delta)); - event_data->frames[i-1].offset = (time_t)(event_data->frames[i-1].timestamp-event_data->start_time); - event_data->frames[i-1].delta = frame_delta; - event_data->frames[i-1].in_db = false; - } - } - event_data->frames[id-1].timestamp = timestamp; - event_data->frames[id-1].offset = (time_t)(event_data->frames[id-1].timestamp-event_data->start_time); - event_data->frames[id-1].delta = id>1?frame_delta:0.0; - event_data->frames[id-1].in_db = true; - last_id = id; - last_delta = delta; - last_timestamp = timestamp; - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - - //for ( int i = 0; i < 250; i++ ) - //{ - //Info( "%d -> %d @ %f (%d)", i+1, event_data->frames[i].timestamp, event_data->frames[i].delta, event_data->frames[i].in_db ); - //} - - mysql_free_result( result ); - - if ( forceEventChange || mode == MODE_ALL_GAPLESS ) - { - if ( replay_rate > 0 ) - curr_stream_time = event_data->frames[0].timestamp; - else - curr_stream_time = event_data->frames[event_data->frame_count-1].timestamp; - } - Debug( 2, "Event:%ld, Frames:%ld, Duration: %.2f", event_data->event_id, event_data->frame_count, event_data->duration ); - - return( true ); + return( true ); } void EventStream::processCommand( const CmdMsg *msg ) { - Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ) - // Check for incoming command - switch( (MsgCommand)msg->msg_data[0] ) + Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ) + // Check for incoming command + switch( (MsgCommand)msg->msg_data[0] ) + { + case CMD_PAUSE : { - case CMD_PAUSE : - { - Debug( 1, "Got PAUSE command" ); + Debug( 1, "Got PAUSE command" ); - // Set paused flag - paused = true; - replay_rate = ZM_RATE_BASE; - last_frame_sent = TV_2_FLOAT( now ); - break; - } - case CMD_PLAY : - { - Debug( 1, "Got PLAY command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - } + // Set paused flag + paused = true; + replay_rate = ZM_RATE_BASE; + last_frame_sent = TV_2_FLOAT( now ); + break; + } + case CMD_PLAY : + { + Debug( 1, "Got PLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } - // If we are in single event mode and at the last frame, replay the current event - if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) - curr_frame_id = 1; + // If we are in single event mode and at the last frame, replay the current event + if ( (mode == MODE_SINGLE) && ((unsigned int)curr_frame_id == event_data->frame_count) ) + curr_frame_id = 1; - replay_rate = ZM_RATE_BASE; - break; - } - case CMD_VARPLAY : - { - Debug( 1, "Got VARPLAY command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - } - replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; - break; - } - case CMD_STOP : - { - Debug( 1, "Got STOP command" ); + replay_rate = ZM_RATE_BASE; + break; + } + case CMD_VARPLAY : + { + Debug( 1, "Got VARPLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; + break; + } + case CMD_STOP : + { + Debug( 1, "Got STOP command" ); - // Clear paused flag - paused = false; - break; - } - case CMD_FASTFWD : - { - Debug( 1, "Got FAST FWD command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - } - // Set play rate - switch ( replay_rate ) - { - case 2 * ZM_RATE_BASE : - replay_rate = 5 * ZM_RATE_BASE; - break; - case 5 * ZM_RATE_BASE : - replay_rate = 10 * ZM_RATE_BASE; - break; - case 10 * ZM_RATE_BASE : - replay_rate = 25 * ZM_RATE_BASE; - break; - case 25 * ZM_RATE_BASE : - case 50 * ZM_RATE_BASE : - replay_rate = 50 * ZM_RATE_BASE; - break; - default : - replay_rate = 2 * ZM_RATE_BASE; - break; - } - break; - } - case CMD_SLOWFWD : - { - Debug( 1, "Got SLOW FWD command" ); - // Set paused flag - paused = true; - // Set play rate - replay_rate = ZM_RATE_BASE; - // Set step - step = 1; - break; - } - case CMD_SLOWREV : - { - Debug( 1, "Got SLOW REV command" ); - // Set paused flag - paused = true; - // Set play rate - replay_rate = ZM_RATE_BASE; - // Set step - step = -1; - break; - } - case CMD_FASTREV : - { - Debug( 1, "Got FAST REV command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - } - // Set play rate - switch ( replay_rate ) - { - case -2 * ZM_RATE_BASE : - replay_rate = -5 * ZM_RATE_BASE; - break; - case -5 * ZM_RATE_BASE : - replay_rate = -10 * ZM_RATE_BASE; - break; - case -10 * ZM_RATE_BASE : - replay_rate = -25 * ZM_RATE_BASE; - break; - case -25 * ZM_RATE_BASE : - case -50 * ZM_RATE_BASE : - replay_rate = -50 * ZM_RATE_BASE; - break; - default : - replay_rate = -2 * ZM_RATE_BASE; - break; - } - break; - } - case CMD_ZOOMIN : - { - x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; - y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; - Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); - switch ( zoom ) - { - case 100: - zoom = 150; - break; - case 150: - zoom = 200; - break; - case 200: - zoom = 300; - break; - case 300: - zoom = 400; - break; - case 400: - default : - zoom = 500; - break; - } - break; - } - case CMD_ZOOMOUT : - { - Debug( 1, "Got ZOOM OUT command" ); - switch ( zoom ) - { - case 500: - zoom = 400; - break; - case 400: - zoom = 300; - break; - case 300: - zoom = 200; - break; - case 200: - zoom = 150; - break; - case 150: - default : - zoom = 100; - break; - } - break; - } - case CMD_PAN : - { - x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; - y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; - Debug( 1, "Got PAN command, to %d,%d", x, y ); - break; - } - case CMD_SCALE : - { - scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; - Debug( 1, "Got SCALE command, to %d", scale ); - break; - } - case CMD_PREV : - { - Debug( 1, "Got PREV command" ); - if ( replay_rate >= 0 ) - curr_frame_id = 0; - else - curr_frame_id = event_data->frame_count+1; - paused = false; - forceEventChange = true; - break; - } - case CMD_NEXT : - { - Debug( 1, "Got NEXT command" ); - if ( replay_rate >= 0 ) - curr_frame_id = event_data->frame_count+1; - else - curr_frame_id = 0; - paused = false; - forceEventChange = true; - break; - } - case CMD_SEEK : - { - int offset = ((unsigned char)msg->msg_data[1]<<24)|((unsigned char)msg->msg_data[2]<<16)|((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; - curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration); - Debug( 1, "Got SEEK command, to %d (new cfid: %d)", offset, curr_frame_id ); - break; - } - case CMD_QUERY : - { - Debug( 1, "Got QUERY command, sending STATUS" ); - break; - } - case CMD_QUIT : - { - Info ("User initiated exit - CMD_QUIT"); - break; - } + // Clear paused flag + paused = false; + break; + } + case CMD_FASTFWD : + { + Debug( 1, "Got FAST FWD command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + // Set play rate + switch ( replay_rate ) + { + case 2 * ZM_RATE_BASE : + replay_rate = 5 * ZM_RATE_BASE; + break; + case 5 * ZM_RATE_BASE : + replay_rate = 10 * ZM_RATE_BASE; + break; + case 10 * ZM_RATE_BASE : + replay_rate = 25 * ZM_RATE_BASE; + break; + case 25 * ZM_RATE_BASE : + case 50 * ZM_RATE_BASE : + replay_rate = 50 * ZM_RATE_BASE; + break; default : - { - // Do nothing, for now - } + replay_rate = 2 * ZM_RATE_BASE; + break; + } + break; } - struct { - int event; - int progress; - int rate; - int zoom; - bool paused; - } status_data; - - status_data.event = event_data->event_id; - status_data.progress = (int)event_data->frames[curr_frame_id-1].offset; - status_data.rate = replay_rate; - status_data.zoom = zoom; - status_data.paused = paused; - Debug( 2, "E:%d, P:%d, p:%d R:%d, Z:%d", - status_data.event, - status_data.paused, - status_data.progress, - status_data.rate, - status_data.zoom - ); - - DataMsg status_msg; - status_msg.msg_type = MSG_DATA_EVENT; - memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) ); - if ( sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) ) < 0 ) + case CMD_SLOWFWD : { - //if ( errno != EAGAIN ) - { - Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); - exit( -1 ); - } + Debug( 1, "Got SLOW FWD command" ); + // Set paused flag + paused = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = 1; + break; } - // quit after sending a status, if this was a quit request - if ((MsgCommand)msg->msg_data[0]==CMD_QUIT) - exit(0); + case CMD_SLOWREV : + { + Debug( 1, "Got SLOW REV command" ); + // Set paused flag + paused = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = -1; + break; + } + case CMD_FASTREV : + { + Debug( 1, "Got FAST REV command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + // Set play rate + switch ( replay_rate ) + { + case -2 * ZM_RATE_BASE : + replay_rate = -5 * ZM_RATE_BASE; + break; + case -5 * ZM_RATE_BASE : + replay_rate = -10 * ZM_RATE_BASE; + break; + case -10 * ZM_RATE_BASE : + replay_rate = -25 * ZM_RATE_BASE; + break; + case -25 * ZM_RATE_BASE : + case -50 * ZM_RATE_BASE : + replay_rate = -50 * ZM_RATE_BASE; + break; + default : + replay_rate = -2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_ZOOMIN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); + switch ( zoom ) + { + case 100: + zoom = 150; + break; + case 150: + zoom = 200; + break; + case 200: + zoom = 300; + break; + case 300: + zoom = 400; + break; + case 400: + default : + zoom = 500; + break; + } + break; + } + case CMD_ZOOMOUT : + { + Debug( 1, "Got ZOOM OUT command" ); + switch ( zoom ) + { + case 500: + zoom = 400; + break; + case 400: + zoom = 300; + break; + case 300: + zoom = 200; + break; + case 200: + zoom = 150; + break; + case 150: + default : + zoom = 100; + break; + } + break; + } + case CMD_PAN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got PAN command, to %d,%d", x, y ); + break; + } + case CMD_SCALE : + { + scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + Debug( 1, "Got SCALE command, to %d", scale ); + break; + } + case CMD_PREV : + { + Debug( 1, "Got PREV command" ); + if ( replay_rate >= 0 ) + curr_frame_id = 0; + else + curr_frame_id = event_data->frame_count+1; + paused = false; + forceEventChange = true; + break; + } + case CMD_NEXT : + { + Debug( 1, "Got NEXT command" ); + if ( replay_rate >= 0 ) + curr_frame_id = event_data->frame_count+1; + else + curr_frame_id = 0; + paused = false; + forceEventChange = true; + break; + } + case CMD_SEEK : + { + int offset = ((unsigned char)msg->msg_data[1]<<24)|((unsigned char)msg->msg_data[2]<<16)|((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration); + Debug( 1, "Got SEEK command, to %d (new cfid: %d)", offset, curr_frame_id ); + break; + } + case CMD_QUERY : + { + Debug( 1, "Got QUERY command, sending STATUS" ); + break; + } + case CMD_QUIT : + { + Info ("User initiated exit - CMD_QUIT"); + break; + } + default : + { + // Do nothing, for now + } + } + struct { + int event; + int progress; + int rate; + int zoom; + bool paused; + } status_data; - updateFrameRate( (double)event_data->frame_count/event_data->duration ); + status_data.event = event_data->event_id; + status_data.progress = (int)event_data->frames[curr_frame_id-1].offset; + status_data.rate = replay_rate; + status_data.zoom = zoom; + status_data.paused = paused; + Debug( 2, "E:%d, P:%d, p:%d R:%d, Z:%d", + status_data.event, + status_data.paused, + status_data.progress, + status_data.rate, + status_data.zoom + ); + + DataMsg status_msg; + status_msg.msg_type = MSG_DATA_EVENT; + memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) ); + if ( sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) ) < 0 ) + { + //if ( errno != EAGAIN ) + { + Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); + exit( -1 ); + } + } + // quit after sending a status, if this was a quit request + if ((MsgCommand)msg->msg_data[0]==CMD_QUIT) + exit(0); + + updateFrameRate( (double)event_data->frame_count/event_data->duration ); } void EventStream::checkEventLoaded() { - bool reload_event = false; - static char sql[ZM_SQL_SML_BUFSIZ]; + bool reload_event = false; + static char sql[ZM_SQL_SML_BUFSIZ]; - if ( curr_frame_id <= 0 ) + if ( curr_frame_id <= 0 ) + { + snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id < %ld order by Id desc limit 1", event_data->monitor_id, event_data->event_id ); + reload_event = true; + } + else if ( (unsigned int)curr_frame_id > event_data->frame_count ) + { + snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id > %ld order by Id asc limit 1", event_data->monitor_id, event_data->event_id ); + reload_event = true; + } + + if ( reload_event ) + { + if ( forceEventChange || mode != MODE_SINGLE ) { - snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id < %ld order by Id desc limit 1", event_data->monitor_id, event_data->event_id ); - reload_event = true; - } - else if ( (unsigned int)curr_frame_id > event_data->frame_count ) - { - snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id > %ld order by Id asc limit 1", event_data->monitor_id, event_data->event_id ); - reload_event = true; - } + //Info( "SQL:%s", sql ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - if ( reload_event ) - { - if ( forceEventChange || mode != MODE_SINGLE ) - { - //Info( "SQL:%s", sql ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + MYSQL_ROW dbrow = mysql_fetch_row( result ); - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - MYSQL_ROW dbrow = mysql_fetch_row( result ); + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( dbrow ) + { + int event_id = atoi(dbrow[0]); + Debug( 1, "Loading new event %d", event_id ); - if ( dbrow ) - { - int event_id = atoi(dbrow[0]); - Debug( 1, "Loading new event %d", event_id ); + loadEventData( event_id ); - loadEventData( event_id ); - - Debug( 2, "Current frame id = %d", curr_frame_id ); - if ( replay_rate < 0 ) - curr_frame_id = event_data->frame_count; - else - curr_frame_id = 1; - Debug( 2, "New frame id = %d", curr_frame_id ); - } - else - { - if ( curr_frame_id <= 0 ) - curr_frame_id = 1; - else - curr_frame_id = event_data->frame_count; - paused = true; - } - mysql_free_result( result ); - forceEventChange = false; - } + Debug( 2, "Current frame id = %d", curr_frame_id ); + if ( replay_rate < 0 ) + curr_frame_id = event_data->frame_count; else - { - if ( curr_frame_id <= 0 ) - curr_frame_id = 1; - else - curr_frame_id = event_data->frame_count; - paused = true; - } + curr_frame_id = 1; + Debug( 2, "New frame id = %d", curr_frame_id ); + } + else + { + if ( curr_frame_id <= 0 ) + curr_frame_id = 1; + else + curr_frame_id = event_data->frame_count; + paused = true; + } + mysql_free_result( result ); + forceEventChange = false; } + else + { + if ( curr_frame_id <= 0 ) + curr_frame_id = 1; + else + curr_frame_id = event_data->frame_count; + paused = true; + } + } } bool EventStream::sendFrame( int delta_us ) { - Debug( 2, "Sending frame %d", curr_frame_id ); + Debug( 2, "Sending frame %d", curr_frame_id ); - static char filepath[PATH_MAX]; - static struct stat filestat; - FILE *fdj = NULL; - - snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id ); + static char filepath[PATH_MAX]; + static struct stat filestat; + FILE *fdj = NULL; + + snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id ); #if HAVE_LIBAVCODEC - if ( type == STREAM_MPEG ) + if ( type == STREAM_MPEG ) + { + Image image( filepath ); + + Image *send_image = prepareImage( &image ); + + if ( !vid_stream ) { - Image image( filepath ); + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); + } + /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_us*1000 ); + } + else +#endif // HAVE_LIBAVCODEC + { + static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; - Image *send_image = prepareImage( &image ); + int img_buffer_size = 0; + uint8_t *img_buffer = temp_img_buffer; - if ( !vid_stream ) - { - vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); - fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); - vid_stream->OpenStream(); - } - /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_us*1000 ); + bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + + if ( type != STREAM_JPEG ) + send_raw = false; + + if ( send_raw ) + { + fdj = fopen( filepath, "rb" ); + if ( !fdj ) + { + Error( "Can't open %s: %s", filepath, strerror(errno) ); + return( false ); + } +#if HAVE_SENDFILE + if( fstat(fileno(fdj),&filestat) < 0 ) { + Error( "Failed getting information about file %s: %s", filepath, strerror(errno) ); + return( false ); + } +#else + img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); +#endif } else -#endif // HAVE_LIBAVCODEC { - static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; + Image image( filepath ); - int img_buffer_size = 0; - uint8_t *img_buffer = temp_img_buffer; + Image *send_image = prepareImage( &image ); - bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); - - fprintf( stdout, "--ZoneMinderFrame\r\n" ); - - if ( type != STREAM_JPEG ) - send_raw = false; - - if ( send_raw ) - { - fdj = fopen( filepath, "rb" ); - if ( !fdj ) - { - Error( "Can't open %s: %s", filepath, strerror(errno) ); - return( false ); - } -#if HAVE_SENDFILE - if( fstat(fileno(fdj),&filestat) < 0 ) { - Error( "Failed getting information about file %s: %s", filepath, strerror(errno) ); - return( false ); - } -#else - img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); -#endif - } - else - { - Image image( filepath ); - - Image *send_image = prepareImage( &image ); - - switch( type ) - { - case STREAM_JPEG : - send_image->EncodeJpeg( img_buffer, &img_buffer_size ); - break; - case STREAM_ZIP : + switch( type ) + { + case STREAM_JPEG : + send_image->EncodeJpeg( img_buffer, &img_buffer_size ); + break; + case STREAM_ZIP : #if HAVE_ZLIB_H - unsigned long zip_buffer_size; - send_image->Zip( img_buffer, &zip_buffer_size ); - img_buffer_size = zip_buffer_size; - break; + unsigned long zip_buffer_size; + send_image->Zip( img_buffer, &zip_buffer_size ); + img_buffer_size = zip_buffer_size; + break; #else - Error("zlib is required for zipped images. Falling back to raw image"); - type = STREAM_RAW; + Error("zlib is required for zipped images. Falling back to raw image"); + type = STREAM_RAW; #endif // HAVE_ZLIB_H - case STREAM_RAW : - img_buffer = (uint8_t*)(send_image->Buffer()); - img_buffer_size = send_image->Size(); - break; - default: - Fatal( "Unexpected frame type %d", type ); - break; - } - } - - switch( type ) - { - case STREAM_JPEG : - fprintf( stdout, "Content-Type: image/jpeg\r\n" ); - break; - case STREAM_RAW : - fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); - break; - case STREAM_ZIP : - fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); - break; - default : - Fatal( "Unexpected frame type %d", type ); - break; - } - - - if(send_raw) { -#if HAVE_SENDFILE - fprintf( stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size ); - if(zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size) { - /* sendfile() failed, use standard way instead */ - img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { - Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno)); - return( false ); - } - } -#else - fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { - Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno)); - return( false ); - } -#endif - fclose(fdj); /* Close the file handle */ - } else { - fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) - { - Error( "Unable to send stream frame: %s", strerror(errno) ); - return( false ); - } - } - - fprintf( stdout, "\r\n\r\n" ); - fflush( stdout ); + case STREAM_RAW : + img_buffer = (uint8_t*)(send_image->Buffer()); + img_buffer_size = send_image->Size(); + break; + default: + Fatal( "Unexpected frame type %d", type ); + break; + } } - last_frame_sent = TV_2_FLOAT( now ); - return( true ); + + switch( type ) + { + case STREAM_JPEG : + fprintf( stdout, "Content-Type: image/jpeg\r\n" ); + break; + case STREAM_RAW : + fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); + break; + case STREAM_ZIP : + fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); + break; + default : + Fatal( "Unexpected frame type %d", type ); + break; + } + + + if(send_raw) { +#if HAVE_SENDFILE + fprintf( stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size ); + if(zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size) { + /* sendfile() failed, use standard way instead */ + img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { + Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno)); + return( false ); + } + } +#else + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { + Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno)); + return( false ); + } +#endif + fclose(fdj); /* Close the file handle */ + } else { + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + } + + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); } void EventStream::runStream() { - Event::Initialise(); + Event::Initialise(); - openComms(); + openComms(); - checkInitialised(); + checkInitialised(); - updateFrameRate( (double)event_data->frame_count/event_data->duration ); + updateFrameRate( (double)event_data->frame_count/event_data->duration ); - if ( type == STREAM_JPEG ) - fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); + if ( type == STREAM_JPEG ) + fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); - if ( !event_data ) + if ( !event_data ) + { + sendTextFrame( "No event data found" ); + exit( 0 ); + } + + unsigned int delta_us = 0; + while( !zm_terminate ) + { + gettimeofday( &now, NULL ); + + while(checkCommandQueue()); + + if ( step != 0 ) + curr_frame_id += step; + + checkEventLoaded(); + + // Get current frame data + FrameData *frame_data = &event_data->frames[curr_frame_id-1]; + + //Info( "cst:%.2f", curr_stream_time ); + //Info( "cfid:%d", curr_frame_id ); + //Info( "fdt:%d", frame_data->timestamp ); + if ( !paused ) { - sendTextFrame( "No event data found" ); - exit( 0 ); + bool in_event = true; + double time_to_event = 0; + if ( replay_rate > 0 ) + { + time_to_event = event_data->frames[0].timestamp - curr_stream_time; + if ( time_to_event > 0 ) + in_event = false; + } + else if ( replay_rate < 0 ) + { + time_to_event = curr_stream_time - event_data->frames[event_data->frame_count-1].timestamp; + if ( time_to_event > 0 ) + in_event = false; + } + if ( !in_event ) + { + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( actual_delta_time > 1 ) + { + static char frame_text[64]; + snprintf( frame_text, sizeof(frame_text), "Time to next event = %d seconds", (int)time_to_event ); + if ( !sendTextFrame( frame_text ) ) + zm_terminate = true; + } + //else + //{ + usleep( STREAM_PAUSE_WAIT ); + //curr_stream_time += (replay_rate>0?1:-1) * ((1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000)); + curr_stream_time += (1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000); + //} + continue; + } } - unsigned int delta_us = 0; - while( !zm_terminate ) + // Figure out if we should send this frame + bool send_frame = false; + if ( !paused ) { - gettimeofday( &now, NULL ); - - while(checkCommandQueue()); - - if ( step != 0 ) - curr_frame_id += step; - - checkEventLoaded(); - - // Get current frame data - FrameData *frame_data = &event_data->frames[curr_frame_id-1]; - - //Info( "cst:%.2f", curr_stream_time ); - //Info( "cfid:%d", curr_frame_id ); - //Info( "fdt:%d", frame_data->timestamp ); - if ( !paused ) - { - bool in_event = true; - double time_to_event = 0; - if ( replay_rate > 0 ) - { - time_to_event = event_data->frames[0].timestamp - curr_stream_time; - if ( time_to_event > 0 ) - in_event = false; - } - else if ( replay_rate < 0 ) - { - time_to_event = curr_stream_time - event_data->frames[event_data->frame_count-1].timestamp; - if ( time_to_event > 0 ) - in_event = false; - } - if ( !in_event ) - { - double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; - if ( actual_delta_time > 1 ) - { - static char frame_text[64]; - snprintf( frame_text, sizeof(frame_text), "Time to next event = %d seconds", (int)time_to_event ); - if ( !sendTextFrame( frame_text ) ) - zm_terminate = true; - } - //else - //{ - usleep( STREAM_PAUSE_WAIT ); - //curr_stream_time += (replay_rate>0?1:-1) * ((1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000)); - curr_stream_time += (1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000); - //} - continue; - } - } - - // Figure out if we should send this frame - bool send_frame = false; - if ( !paused ) - { - // If we are streaming and this frame is due to be sent - if ( ((curr_frame_id-1)%frame_mod) == 0 ) - { - delta_us = (unsigned int)(frame_data->delta * 1000000); - // if effective > base we should speed up frame delivery - delta_us = (unsigned int)((delta_us * base_fps)/effective_fps); - // but must not exceed maxfps - delta_us = max(delta_us, 1000000 / maxfps); - send_frame = true; - } - } - else if ( step != 0 ) - { - // We are paused and are just stepping forward or backward one frame - step = 0; - send_frame = true; - } - else - { - // We are paused, and doing nothing - double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; - if ( actual_delta_time > MAX_STREAM_DELAY ) - { - // Send keepalive - Debug( 2, "Sending keepalive frame" ); - send_frame = true; - } - } - - if ( send_frame ) - if ( !sendFrame( delta_us ) ) - zm_terminate = true; - - curr_stream_time = frame_data->timestamp; - - if ( !paused ) - { - curr_frame_id += replay_rate>0?1:-1; - if ( send_frame && type != STREAM_MPEG ) - { - Debug( 3, "dUs: %d", delta_us ); - usleep( delta_us ); - } - } - else - { - usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); - } + // If we are streaming and this frame is due to be sent + if ( ((curr_frame_id-1)%frame_mod) == 0 ) + { + delta_us = (unsigned int)(frame_data->delta * 1000000); + // if effective > base we should speed up frame delivery + delta_us = (unsigned int)((delta_us * base_fps)/effective_fps); + // but must not exceed maxfps + delta_us = max(delta_us, 1000000 / maxfps); + send_frame = true; + } } + else if ( step != 0 ) + { + // We are paused and are just stepping forward or backward one frame + step = 0; + send_frame = true; + } + else + { + // We are paused, and doing nothing + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( actual_delta_time > MAX_STREAM_DELAY ) + { + // Send keepalive + Debug( 2, "Sending keepalive frame" ); + send_frame = true; + } + } + + if ( send_frame ) + if ( !sendFrame( delta_us ) ) + zm_terminate = true; + + curr_stream_time = frame_data->timestamp; + + if ( !paused ) + { + curr_frame_id += replay_rate>0?1:-1; + if ( send_frame && type != STREAM_MPEG ) + { + Debug( 3, "dUs: %d", delta_us ); + usleep( delta_us ); + } + } + else + { + usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); + } + } #if HAVE_LIBAVCODEC - if ( type == STREAM_MPEG ) - delete vid_stream; + if ( type == STREAM_MPEG ) + delete vid_stream; #endif // HAVE_LIBAVCODEC - closeComms(); + closeComms(); } diff --git a/src/zm_event.h b/src/zm_event.h index f50a5bf06..afb274947 100644 --- a/src/zm_event.h +++ b/src/zm_event.h @@ -41,7 +41,7 @@ class Zone; class Monitor; -#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored +#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored // // Class describing events, i.e. captured periods of activity. @@ -51,219 +51,219 @@ class Event friend class EventStream; protected: - static bool initialised; - static char capture_file_format[PATH_MAX]; - static char analyse_file_format[PATH_MAX]; - static char general_file_format[PATH_MAX]; + static bool initialised; + static char capture_file_format[PATH_MAX]; + static char analyse_file_format[PATH_MAX]; + static char general_file_format[PATH_MAX]; protected: - static int sd; + static int sd; public: - typedef std::set StringSet; - typedef std::map StringSetMap; + typedef std::set StringSet; + typedef std::map StringSetMap; protected: - typedef enum { NORMAL, BULK, ALARM } FrameType; + typedef enum { NORMAL, BULK, ALARM } FrameType; - struct PreAlarmData - { - Image *image; - struct timeval timestamp; - unsigned int score; - Image *alarm_frame; - }; + struct PreAlarmData + { + Image *image; + struct timeval timestamp; + unsigned int score; + Image *alarm_frame; + }; - static int pre_alarm_count; - static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES]; + static int pre_alarm_count; + static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES]; protected: - unsigned int id; - Monitor *monitor; - struct timeval start_time; - struct timeval end_time; - std::string cause; - StringSetMap noteSetMap; - int frames; - int alarm_frames; - unsigned int tot_score; - unsigned int max_score; - char path[PATH_MAX]; + unsigned int id; + Monitor *monitor; + struct timeval start_time; + struct timeval end_time; + std::string cause; + StringSetMap noteSetMap; + int frames; + int alarm_frames; + unsigned int tot_score; + unsigned int max_score; + char path[PATH_MAX]; protected: - int last_db_frame; + int last_db_frame; protected: - static void Initialise() - { - if ( initialised ) - return; + static void Initialise() + { + if ( initialised ) + return; - snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits ); - snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits ); - snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits ); + snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits ); + snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits ); + snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits ); - initialised = true; - } + initialised = true; + } - void createNotes( std::string ¬es ); + void createNotes( std::string ¬es ); public: - static bool OpenFrameSocket( int ); - static bool ValidateFrameSocket( int ); + static bool OpenFrameSocket( int ); + static bool ValidateFrameSocket( int ); public: - Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap ); - ~Event(); + Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap ); + ~Event(); - int Id() const { return( id ); } - const std::string &Cause() { return( cause ); } - int Frames() const { return( frames ); } - int AlarmFrames() const { return( alarm_frames ); } + int Id() const { return( id ); } + const std::string &Cause() { return( cause ); } + int Frames() const { return( frames ); } + int AlarmFrames() const { return( alarm_frames ); } - const struct timeval &StartTime() const { return( start_time ); } - const struct timeval &EndTime() const { return( end_time ); } - struct timeval &EndTime() { return( end_time ); } + const struct timeval &StartTime() const { return( start_time ); } + const struct timeval &EndTime() const { return( end_time ); } + struct timeval &EndTime() { return( end_time ); } - bool SendFrameImage( const Image *image, bool alarm_frame=false ); - bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ); + bool SendFrameImage( const Image *image, bool alarm_frame=false ); + bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ); - void updateNotes( const StringSetMap &stringSetMap ); + void updateNotes( const StringSetMap &stringSetMap ); - void AddFrames( int n_frames, Image **images, struct timeval **timestamps ); - void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ); + void AddFrames( int n_frames, Image **images, struct timeval **timestamps ); + void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ); private: - void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ); + void AddFramesInternal( int n_frames, int start_frame, Image **images, struct timeval **timestamps ); public: - static const char *getSubPath( struct tm *time ) - { - static char subpath[PATH_MAX] = ""; - snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); - return( subpath ); - } - static const char *getSubPath( time_t *time ) - { - return( Event::getSubPath( localtime( time ) ) ); - } + static const char *getSubPath( struct tm *time ) + { + static char subpath[PATH_MAX] = ""; + snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); + return( subpath ); + } + static const char *getSubPath( time_t *time ) + { + return( Event::getSubPath( localtime( time ) ) ); + } public: - static int PreAlarmCount() - { - return( pre_alarm_count ); - } - static void EmptyPreAlarmFrames() - { - if ( pre_alarm_count > 0 ) - { - for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ ) - { - delete pre_alarm_data[i].image; - delete pre_alarm_data[i].alarm_frame; - } - memset( pre_alarm_data, 0, sizeof(pre_alarm_data) ); - } - pre_alarm_count = 0; - } - static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ) - { - pre_alarm_data[pre_alarm_count].image = new Image( *image ); - pre_alarm_data[pre_alarm_count].timestamp = timestamp; - pre_alarm_data[pre_alarm_count].score = score; - if ( alarm_frame ) - { - pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame ); - } - pre_alarm_count++; - } - void SavePreAlarmFrames() - { - for ( int i = 0; i < pre_alarm_count; i++ ) - { - AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame ); - } - EmptyPreAlarmFrames(); - } + static int PreAlarmCount() + { + return( pre_alarm_count ); + } + static void EmptyPreAlarmFrames() + { + if ( pre_alarm_count > 0 ) + { + for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ ) + { + delete pre_alarm_data[i].image; + delete pre_alarm_data[i].alarm_frame; + } + memset( pre_alarm_data, 0, sizeof(pre_alarm_data) ); + } + pre_alarm_count = 0; + } + static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ) + { + pre_alarm_data[pre_alarm_count].image = new Image( *image ); + pre_alarm_data[pre_alarm_count].timestamp = timestamp; + pre_alarm_data[pre_alarm_count].score = score; + if ( alarm_frame ) + { + pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame ); + } + pre_alarm_count++; + } + void SavePreAlarmFrames() + { + for ( int i = 0; i < pre_alarm_count; i++ ) + { + AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame ); + } + EmptyPreAlarmFrames(); + } }; class EventStream : public StreamBase { public: - typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode; + typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode; protected: - struct FrameData { - //unsigned long id; - time_t timestamp; - time_t offset; - double delta; - bool in_db; - }; + struct FrameData { + //unsigned long id; + time_t timestamp; + time_t offset; + double delta; + bool in_db; + }; - struct EventData - { - unsigned long event_id; - unsigned long monitor_id; - unsigned long frame_count; - time_t start_time; - double duration; - char path[PATH_MAX]; - int n_frames; - FrameData *frames; - }; + struct EventData + { + unsigned long event_id; + unsigned long monitor_id; + unsigned long frame_count; + time_t start_time; + double duration; + char path[PATH_MAX]; + int n_frames; + FrameData *frames; + }; protected: - static const int STREAM_PAUSE_WAIT = 250000; // Microseconds + static const int STREAM_PAUSE_WAIT = 250000; // Microseconds - static const StreamMode DEFAULT_MODE = MODE_SINGLE; + static const StreamMode DEFAULT_MODE = MODE_SINGLE; protected: - StreamMode mode; - bool forceEventChange; + StreamMode mode; + bool forceEventChange; protected: - int curr_frame_id; - double curr_stream_time; + int curr_frame_id; + double curr_stream_time; - EventData *event_data; + EventData *event_data; protected: - bool loadEventData( int event_id ); - bool loadInitialEventData( int init_event_id, int init_frame_id ); - bool loadInitialEventData( int monitor_id, time_t event_time ); + bool loadEventData( int event_id ); + bool loadInitialEventData( int init_event_id, int init_frame_id ); + bool loadInitialEventData( int monitor_id, time_t event_time ); - void checkEventLoaded(); - void processCommand( const CmdMsg *msg ); - bool sendFrame( int delta_us ); + void checkEventLoaded(); + void processCommand( const CmdMsg *msg ); + bool sendFrame( int delta_us ); public: - EventStream() - { - mode = DEFAULT_MODE; + EventStream() + { + mode = DEFAULT_MODE; - forceEventChange = false; + forceEventChange = false; - curr_frame_id = 0; - curr_stream_time = 0.0; + curr_frame_id = 0; + curr_stream_time = 0.0; - event_data = 0; - } - void setStreamStart( int init_event_id, int init_frame_id=0 ) - { - loadInitialEventData( init_event_id, init_frame_id ); - loadMonitor( event_data->monitor_id ); - } - void setStreamStart( int monitor_id, time_t event_time ) - { - loadInitialEventData( monitor_id, event_time ); - loadMonitor( monitor_id ); - } - void setStreamMode( StreamMode p_mode ) - { - mode = p_mode; - } - void runStream(); + event_data = 0; + } + void setStreamStart( int init_event_id, int init_frame_id=0 ) + { + loadInitialEventData( init_event_id, init_frame_id ); + loadMonitor( event_data->monitor_id ); + } + void setStreamStart( int monitor_id, time_t event_time ) + { + loadInitialEventData( monitor_id, event_time ); + loadMonitor( monitor_id ); + } + void setStreamMode( StreamMode p_mode ) + { + mode = p_mode; + } + void runStream(); }; #endif // ZM_EVENT_H diff --git a/src/zm_exception.h b/src/zm_exception.h index 4af60bfa6..a503be7c9 100644 --- a/src/zm_exception.h +++ b/src/zm_exception.h @@ -27,42 +27,42 @@ class Exception { protected: - typedef enum { INFO, WARNING, ERROR, FATAL } Severity; + typedef enum { INFO, WARNING, ERROR, FATAL } Severity; protected: - std::string mMessage; - Severity mSeverity; + std::string mMessage; + Severity mSeverity; public: - Exception( const std::string &message, Severity severity=ERROR ) : mMessage( message ), mSeverity( severity ) - { - } + Exception( const std::string &message, Severity severity=ERROR ) : mMessage( message ), mSeverity( severity ) + { + } public: - const std::string &getMessage() const - { - return( mMessage ); - } - Severity getSeverity() const - { - return( mSeverity ); - } - bool isInfo() const - { - return( mSeverity == INFO ); - } - bool isWarning() const - { - return( mSeverity == WARNING ); - } - bool isError() const - { - return( mSeverity == ERROR ); - } - bool isFatal() const - { - return( mSeverity == FATAL ); - } + const std::string &getMessage() const + { + return( mMessage ); + } + Severity getSeverity() const + { + return( mSeverity ); + } + bool isInfo() const + { + return( mSeverity == INFO ); + } + bool isWarning() const + { + return( mSeverity == WARNING ); + } + bool isError() const + { + return( mSeverity == ERROR ); + } + bool isFatal() const + { + return( mSeverity == FATAL ); + } }; #endif // ZM_EXCEPTION_H diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp index 86817c223..fc20f6286 100644 --- a/src/zm_ffmpeg.cpp +++ b/src/zm_ffmpeg.cpp @@ -25,210 +25,210 @@ #if HAVE_LIBAVUTIL enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder) { - enum _AVPIXELFORMAT pf; + enum _AVPIXELFORMAT pf; - Debug(8,"Colours: %d SubpixelOrder: %d",p_colours,p_subpixelorder); + Debug(8,"Colours: %d SubpixelOrder: %d",p_colours,p_subpixelorder); - switch(p_colours) { - case ZM_COLOUR_RGB24: - { - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { - /* BGR subpixel order */ - pf = AV_PIX_FMT_BGR24; - } else { - /* Assume RGB subpixel order */ - pf = AV_PIX_FMT_RGB24; - } - break; - } - case ZM_COLOUR_RGB32: - { - if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - /* ARGB subpixel order */ - pf = AV_PIX_FMT_ARGB; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - /* ABGR subpixel order */ - pf = AV_PIX_FMT_ABGR; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* BGRA subpixel order */ - pf = AV_PIX_FMT_BGRA; - } else { - /* Assume RGBA subpixel order */ - pf = AV_PIX_FMT_RGBA; - } - break; - } - case ZM_COLOUR_GRAY8: - pf = AV_PIX_FMT_GRAY8; - break; - default: - Panic("Unexpected colours: %d",p_colours); - pf = AV_PIX_FMT_GRAY8; /* Just to shush gcc variable may be unused warning */ - break; - } + switch(p_colours) { + case ZM_COLOUR_RGB24: + { + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + pf = AV_PIX_FMT_BGR24; + } else { + /* Assume RGB subpixel order */ + pf = AV_PIX_FMT_RGB24; + } + break; + } + case ZM_COLOUR_RGB32: + { + if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + pf = AV_PIX_FMT_ARGB; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + pf = AV_PIX_FMT_ABGR; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + pf = AV_PIX_FMT_BGRA; + } else { + /* Assume RGBA subpixel order */ + pf = AV_PIX_FMT_RGBA; + } + break; + } + case ZM_COLOUR_GRAY8: + pf = AV_PIX_FMT_GRAY8; + break; + default: + Panic("Unexpected colours: %d",p_colours); + pf = AV_PIX_FMT_GRAY8; /* Just to shush gcc variable may be unused warning */ + break; + } - return pf; + return pf; } #endif // HAVE_LIBAVUTIL #if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL SWScale::SWScale() : gotdefaults(false), swscale_ctx(NULL), input_avframe(NULL), output_avframe(NULL) { - Debug(4,"SWScale object created"); + Debug(4,"SWScale object created"); - /* Allocate AVFrame for the input */ + /* Allocate AVFrame for the input */ #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - input_avframe = av_frame_alloc(); + input_avframe = av_frame_alloc(); #else - input_avframe = avcodec_alloc_frame(); + input_avframe = avcodec_alloc_frame(); #endif - if(input_avframe == NULL) { - Fatal("Failed allocating AVFrame for the input"); - } + if(input_avframe == NULL) { + Fatal("Failed allocating AVFrame for the input"); + } - /* Allocate AVFrame for the output */ + /* Allocate AVFrame for the output */ #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - output_avframe = av_frame_alloc(); + output_avframe = av_frame_alloc(); #else - output_avframe = avcodec_alloc_frame(); + output_avframe = avcodec_alloc_frame(); #endif - if(output_avframe == NULL) { - Fatal("Failed allocating AVFrame for the output"); - } + if(output_avframe == NULL) { + Fatal("Failed allocating AVFrame for the output"); + } } SWScale::~SWScale() { - /* Free up everything */ + /* Free up everything */ #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &input_avframe ); + av_frame_free( &input_avframe ); #else - av_freep( &input_avframe ); + av_freep( &input_avframe ); #endif - //input_avframe = NULL; + //input_avframe = NULL; #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &output_avframe ); + av_frame_free( &output_avframe ); #else - av_freep( &output_avframe ); + av_freep( &output_avframe ); #endif - //output_avframe = NULL; + //output_avframe = NULL; - if(swscale_ctx) { - sws_freeContext(swscale_ctx); - swscale_ctx = NULL; - } - - Debug(4,"SWScale object destroyed"); + if(swscale_ctx) { + sws_freeContext(swscale_ctx); + swscale_ctx = NULL; + } + + Debug(4,"SWScale object destroyed"); } int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) { - /* Assign the defaults */ - default_input_pf = in_pf; - default_output_pf = out_pf; - default_width = width; - default_height = height; + /* Assign the defaults */ + default_input_pf = in_pf; + default_output_pf = out_pf; + default_width = width; + default_height = height; - gotdefaults = true; + gotdefaults = true; - return 0; + return 0; } int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) { - /* Parameter checking */ - if(in_buffer == NULL || out_buffer == NULL) { - Error("NULL Input or output buffer"); - return -1; - } - if(in_pf == 0 || out_pf == 0) { - Error("Invalid input or output pixel formats"); - return -2; - } - if(!width || !height) { - Error("Invalid width or height"); - return -3; - } + /* Parameter checking */ + if(in_buffer == NULL || out_buffer == NULL) { + Error("NULL Input or output buffer"); + return -1; + } + if(in_pf == 0 || out_pf == 0) { + Error("Invalid input or output pixel formats"); + return -2; + } + if(!width || !height) { + Error("Invalid width or height"); + return -3; + } #if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0) - /* Warn if the input or output pixelformat is not supported */ - if(!sws_isSupportedInput(in_pf)) { - Warning("swscale does not support the input format: %c%c%c%c",(in_pf)&0xff,((in_pf)&0xff),((in_pf>>16)&0xff),((in_pf>>24)&0xff)); - } - if(!sws_isSupportedOutput(out_pf)) { - Warning("swscale does not support the output format: %c%c%c%c",(out_pf)&0xff,((out_pf>>8)&0xff),((out_pf>>16)&0xff),((out_pf>>24)&0xff)); - } + /* Warn if the input or output pixelformat is not supported */ + if(!sws_isSupportedInput(in_pf)) { + Warning("swscale does not support the input format: %c%c%c%c",(in_pf)&0xff,((in_pf)&0xff),((in_pf>>16)&0xff),((in_pf>>24)&0xff)); + } + if(!sws_isSupportedOutput(out_pf)) { + Warning("swscale does not support the output format: %c%c%c%c",(out_pf)&0xff,((out_pf>>8)&0xff),((out_pf>>16)&0xff),((out_pf>>24)&0xff)); + } #endif - /* Check the buffer sizes */ - size_t insize = avpicture_get_size(in_pf, width, height); - if(insize != in_buffer_size) { - Error("The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size); - return -4; - } - size_t outsize = avpicture_get_size(out_pf, width, height); - if(outsize < out_buffer_size) { - Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size); - return -5; - } + /* Check the buffer sizes */ + size_t insize = avpicture_get_size(in_pf, width, height); + if(insize != in_buffer_size) { + Error("The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size); + return -4; + } + size_t outsize = avpicture_get_size(out_pf, width, height); + if(outsize < out_buffer_size) { + Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size); + return -5; + } - /* Get the context */ - swscale_ctx = sws_getCachedContext( NULL, width, height, in_pf, width, height, out_pf, 0, NULL, NULL, NULL ); - if(swscale_ctx == NULL) { - Error("Failed getting swscale context"); - return -6; - } + /* Get the context */ + swscale_ctx = sws_getCachedContext( NULL, width, height, in_pf, width, height, out_pf, 0, NULL, NULL, NULL ); + if(swscale_ctx == NULL) { + Error("Failed getting swscale context"); + return -6; + } - /* Fill in the buffers */ - if(!avpicture_fill( (AVPicture*)input_avframe, (uint8_t*)in_buffer, in_pf, width, height ) ) { - Error("Failed filling input frame with input buffer"); - return -7; - } - if(!avpicture_fill( (AVPicture*)output_avframe, out_buffer, out_pf, width, height ) ) { - Error("Failed filling output frame with output buffer"); - return -8; - } + /* Fill in the buffers */ + if(!avpicture_fill( (AVPicture*)input_avframe, (uint8_t*)in_buffer, in_pf, width, height ) ) { + Error("Failed filling input frame with input buffer"); + return -7; + } + if(!avpicture_fill( (AVPicture*)output_avframe, out_buffer, out_pf, width, height ) ) { + Error("Failed filling output frame with output buffer"); + return -8; + } - /* Do the conversion */ - if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) { - Error("swscale conversion failed"); - return -10; - } + /* Do the conversion */ + if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) { + Error("swscale conversion failed"); + return -10; + } - return 0; + return 0; } int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) { - if(img->Width() != width) { - Error("Source image width differs. Source: %d Output: %d",img->Width(), width); - return -12; - } + if(img->Width() != width) { + Error("Source image width differs. Source: %d Output: %d",img->Width(), width); + return -12; + } - if(img->Height() != height) { - Error("Source image height differs. Source: %d Output: %d",img->Height(), height); - return -13; - } + if(img->Height() != height) { + Error("Source image height differs. Source: %d Output: %d",img->Height(), height); + return -13; + } - return Convert(img->Buffer(),img->Size(),out_buffer,out_buffer_size,in_pf,out_pf,width,height); + return Convert(img->Buffer(),img->Size(),out_buffer,out_buffer_size,in_pf,out_pf,width,height); } int SWScale::ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size) { - if(!gotdefaults) { - Error("Defaults are not set"); - return -24; - } + if(!gotdefaults) { + Error("Defaults are not set"); + return -24; + } - return Convert(img,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height); + return Convert(img,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height); } int SWScale::ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size) { - if(!gotdefaults) { - Error("Defaults are not set"); - return -24; - } + if(!gotdefaults) { + Error("Defaults are not set"); + return -24; + } - return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height); + return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height); } #endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h index 031a10671..507e5cf4b 100644 --- a/src/zm_ffmpeg.h +++ b/src/zm_ffmpeg.h @@ -39,8 +39,8 @@ extern "C" { * b and c the minor and micro versions of libav * d and e the minor and micro versions of FFmpeg */ #define LIBAVUTIL_VERSION_CHECK(a, b, c, d, e) \ - ( (LIBAVUTIL_VERSION_MICRO < 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ - (LIBAVUTIL_VERSION_MICRO >= 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) + ( (LIBAVUTIL_VERSION_MICRO < 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ + (LIBAVUTIL_VERSION_MICRO >= 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) #if LIBAVUTIL_VERSION_CHECK(50, 29, 0, 29, 0) #include @@ -53,55 +53,55 @@ extern "C" { #include #include #endif /* HAVE_LIBAVUTIL_AVUTIL_H */ - + #if defined(HAVE_LIBAVUTIL_AVUTIL_H) #if LIBAVUTIL_VERSION_CHECK(51, 42, 0, 74, 100) - #define _AVPIXELFORMAT AVPixelFormat + #define _AVPIXELFORMAT AVPixelFormat #else - #define _AVPIXELFORMAT PixelFormat - #define AV_PIX_FMT_NONE PIX_FMT_NONE - #define AV_PIX_FMT_RGB444 PIX_FMT_RGB444 - #define AV_PIX_FMT_RGB555 PIX_FMT_RGB555 - #define AV_PIX_FMT_RGB565 PIX_FMT_RGB565 - #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 - #define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 - #define AV_PIX_FMT_BGRA PIX_FMT_BGRA - #define AV_PIX_FMT_ARGB PIX_FMT_ARGB - #define AV_PIX_FMT_ABGR PIX_FMT_ABGR - #define AV_PIX_FMT_RGBA PIX_FMT_RGBA - #define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8 - #define AV_PIX_FMT_YUYV422 PIX_FMT_YUYV422 - #define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P - #define AV_PIX_FMT_YUV411P PIX_FMT_YUV411P - #define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P - #define AV_PIX_FMT_YUV410P PIX_FMT_YUV410P - #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P - #define AV_PIX_FMT_YUVJ444P PIX_FMT_YUVJ444P - #define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422 - #define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P - #define AV_PIX_FMT_YUVJ422P PIX_FMT_YUVJ422P - #define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422 - #define AV_PIX_FMT_UYYVYY411 PIX_FMT_UYYVYY411 - #define AV_PIX_FMT_BGR565 PIX_FMT_BGR565 - #define AV_PIX_FMT_BGR555 PIX_FMT_BGR555 - #define AV_PIX_FMT_BGR8 PIX_FMT_BGR8 - #define AV_PIX_FMT_BGR4 PIX_FMT_BGR4 - #define AV_PIX_FMT_BGR4_BYTE PIX_FMT_BGR4_BYTE - #define AV_PIX_FMT_RGB8 PIX_FMT_RGB8 - #define AV_PIX_FMT_RGB4 PIX_FMT_RGB4 - #define AV_PIX_FMT_RGB4_BYTE PIX_FMT_RGB4_BYTE - #define AV_PIX_FMT_NV12 PIX_FMT_NV12 - #define AV_PIX_FMT_NV21 PIX_FMT_NV21 - #define AV_PIX_FMT_RGB32_1 PIX_FMT_RGB32_1 - #define AV_PIX_FMT_BGR32_1 PIX_FMT_BGR32_1 - #define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE - #define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE - #define AV_PIX_FMT_YUV440P PIX_FMT_YUV440P - #define AV_PIX_FMT_YUVJ440P PIX_FMT_YUVJ440P - #define AV_PIX_FMT_YUVA420P PIX_FMT_YUVA420P - //#define AV_PIX_FMT_VDPAU_H264 PIX_FMT_VDPAU_H264 - //#define AV_PIX_FMT_VDPAU_MPEG1 PIX_FMT_VDPAU_MPEG1 - //#define AV_PIX_FMT_VDPAU_MPEG2 PIX_FMT_VDPAU_MPEG2 + #define _AVPIXELFORMAT PixelFormat + #define AV_PIX_FMT_NONE PIX_FMT_NONE + #define AV_PIX_FMT_RGB444 PIX_FMT_RGB444 + #define AV_PIX_FMT_RGB555 PIX_FMT_RGB555 + #define AV_PIX_FMT_RGB565 PIX_FMT_RGB565 + #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24 + #define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 + #define AV_PIX_FMT_BGRA PIX_FMT_BGRA + #define AV_PIX_FMT_ARGB PIX_FMT_ARGB + #define AV_PIX_FMT_ABGR PIX_FMT_ABGR + #define AV_PIX_FMT_RGBA PIX_FMT_RGBA + #define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8 + #define AV_PIX_FMT_YUYV422 PIX_FMT_YUYV422 + #define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P + #define AV_PIX_FMT_YUV411P PIX_FMT_YUV411P + #define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P + #define AV_PIX_FMT_YUV410P PIX_FMT_YUV410P + #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P + #define AV_PIX_FMT_YUVJ444P PIX_FMT_YUVJ444P + #define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422 + #define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P + #define AV_PIX_FMT_YUVJ422P PIX_FMT_YUVJ422P + #define AV_PIX_FMT_UYVY422 PIX_FMT_UYVY422 + #define AV_PIX_FMT_UYYVYY411 PIX_FMT_UYYVYY411 + #define AV_PIX_FMT_BGR565 PIX_FMT_BGR565 + #define AV_PIX_FMT_BGR555 PIX_FMT_BGR555 + #define AV_PIX_FMT_BGR8 PIX_FMT_BGR8 + #define AV_PIX_FMT_BGR4 PIX_FMT_BGR4 + #define AV_PIX_FMT_BGR4_BYTE PIX_FMT_BGR4_BYTE + #define AV_PIX_FMT_RGB8 PIX_FMT_RGB8 + #define AV_PIX_FMT_RGB4 PIX_FMT_RGB4 + #define AV_PIX_FMT_RGB4_BYTE PIX_FMT_RGB4_BYTE + #define AV_PIX_FMT_NV12 PIX_FMT_NV12 + #define AV_PIX_FMT_NV21 PIX_FMT_NV21 + #define AV_PIX_FMT_RGB32_1 PIX_FMT_RGB32_1 + #define AV_PIX_FMT_BGR32_1 PIX_FMT_BGR32_1 + #define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE + #define AV_PIX_FMT_GRAY16LE PIX_FMT_GRAY16LE + #define AV_PIX_FMT_YUV440P PIX_FMT_YUV440P + #define AV_PIX_FMT_YUVJ440P PIX_FMT_YUVJ440P + #define AV_PIX_FMT_YUVA420P PIX_FMT_YUVA420P + //#define AV_PIX_FMT_VDPAU_H264 PIX_FMT_VDPAU_H264 + //#define AV_PIX_FMT_VDPAU_MPEG1 PIX_FMT_VDPAU_MPEG1 + //#define AV_PIX_FMT_VDPAU_MPEG2 PIX_FMT_VDPAU_MPEG2 #endif #endif /* HAVE_LIBAVUTIL_AVUTIL_H */ @@ -116,8 +116,8 @@ extern "C" { * b and c the minor and micro versions of libav * d and e the minor and micro versions of FFmpeg */ #define LIBAVCODEC_VERSION_CHECK(a, b, c, d, e) \ - ( (LIBAVCODEC_VERSION_MICRO < 100 && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ - (LIBAVCODEC_VERSION_MICRO >= 100 && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) + ( (LIBAVCODEC_VERSION_MICRO < 100 && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ + (LIBAVCODEC_VERSION_MICRO >= 100 && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) #elif HAVE_FFMPEG_AVCODEC_H #include @@ -125,9 +125,9 @@ extern "C" { #if defined(HAVE_LIBAVCODEC_AVCODEC_H) #if LIBAVCODEC_VERSION_CHECK(54, 25, 0, 51, 100) - #define _AVCODECID AVCodecID + #define _AVCODECID AVCodecID #else - #define _AVCODECID CodecID + #define _AVCODECID CodecID #endif #endif /* HAVE_LIBAVCODEC_AVCODEC_H */ @@ -141,8 +141,8 @@ extern "C" { * b and c the minor and micro versions of libav * d and e the minor and micro versions of FFmpeg */ #define LIBAVFORMAT_VERSION_CHECK(a, b, c, d, e) \ - ( (LIBAVFORMAT_VERSION_MICRO < 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ - (LIBAVFORMAT_VERSION_MICRO >= 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) + ( (LIBAVFORMAT_VERSION_MICRO < 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ + (LIBAVFORMAT_VERSION_MICRO >= 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) #elif HAVE_FFMPEG_AVFORMAT_H #include @@ -157,8 +157,8 @@ extern "C" { * b and c the minor and micro versions of libav * d and e the minor and micro versions of FFmpeg */ #define LIBAVDEVICE_VERSION_CHECK(a, b, c, d, e) \ - ( (LIBAVDEVICE_VERSION_MICRO < 100 && LIBAVDEVICE_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ - (LIBAVDEVICE_VERSION_MICRO >= 100 && LIBAVDEVICE_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) + ( (LIBAVDEVICE_VERSION_MICRO < 100 && LIBAVDEVICE_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ + (LIBAVDEVICE_VERSION_MICRO >= 100 && LIBAVDEVICE_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) #elif HAVE_FFMPEG_AVDEVICE_H #include @@ -173,8 +173,8 @@ extern "C" { * b and c the minor and micro versions of libav * d and e the minor and micro versions of FFmpeg */ #define LIBSWSCALE_VERSION_CHECK(a, b, c, d, e) \ - ( (LIBSWSCALE_VERSION_MICRO < 100 && LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ - (LIBSWSCALE_VERSION_MICRO >= 100 && LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) + ( (LIBSWSCALE_VERSION_MICRO < 100 && LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \ + (LIBSWSCALE_VERSION_MICRO >= 100 && LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(a, d, e) ) ) #elif HAVE_FFMPEG_SWSCALE_H #include @@ -203,23 +203,23 @@ enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subp #if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL class SWScale { public: - SWScale(); - ~SWScale(); - int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); - int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size); - int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size); - int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); - int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); + SWScale(); + ~SWScale(); + int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); + int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size); + int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size); + int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); + int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height); protected: - bool gotdefaults; - struct SwsContext* swscale_ctx; - AVFrame* input_avframe; - AVFrame* output_avframe; - enum _AVPIXELFORMAT default_input_pf; - enum _AVPIXELFORMAT default_output_pf; - unsigned int default_width; - unsigned int default_height; + bool gotdefaults; + struct SwsContext* swscale_ctx; + AVFrame* input_avframe; + AVFrame* output_avframe; + enum _AVPIXELFORMAT default_input_pf; + enum _AVPIXELFORMAT default_output_pf; + unsigned int default_width; + unsigned int default_height; }; #endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL @@ -256,21 +256,21 @@ protected: */ #ifdef __cplusplus - inline static const std::string av_make_error_string(int errnum) - { - char errbuf[AV_ERROR_MAX_STRING_SIZE]; + inline static const std::string av_make_error_string(int errnum) + { + char errbuf[AV_ERROR_MAX_STRING_SIZE]; #if LIBAVUTIL_VERSION_CHECK(50, 13, 0, 13, 0) - av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE); + av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE); #else - snprintf(errbuf, AV_ERROR_MAX_STRING_SIZE, "libav error %d", errnum); + snprintf(errbuf, AV_ERROR_MAX_STRING_SIZE, "libav error %d", errnum); #endif - return (std::string)errbuf; - } + return (std::string)errbuf; + } - #undef av_err2str - #define av_err2str(errnum) av_make_error_string(errnum).c_str() + #undef av_err2str + #define av_err2str(errnum) av_make_error_string(errnum).c_str() - #endif // __cplusplus + #endif // __cplusplus #endif // ( HAVE_LIBAVUTIL_AVUTIL_H || HAVE_LIBAVCODEC_AVCODEC_H || HAVE_LIBAVFORMAT_AVFORMAT_H || HAVE_LIBAVDEVICE_AVDEVICE_H ) diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 380e4ba39..1b35c6a0a 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -28,71 +28,71 @@ #endif #ifdef SOLARIS -#include // for ESRCH +#include // for ESRCH #include #include #endif FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), - mPath( p_path ), - mMethod( p_method ), - mOptions( p_options ) + Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + mPath( p_path ), + mMethod( p_method ), + mOptions( p_options ) { - if ( capture ) - { - Initialise(); - } - - mFormatContext = NULL; - mVideoStreamId = -1; - mCodecContext = NULL; - mCodec = NULL; - mRawFrame = NULL; - mFrame = NULL; - frameCount = 0; - mIsOpening = false; - mCanCapture = false; - mOpenStart = 0; - mReopenThread = 0; - -#if HAVE_LIBSWSCALE - mConvertContext = NULL; + if ( capture ) + { + Initialise(); + } + + mFormatContext = NULL; + mVideoStreamId = -1; + mCodecContext = NULL; + mCodec = NULL; + mRawFrame = NULL; + mFrame = NULL; + frameCount = 0; + mIsOpening = false; + mCanCapture = false; + mOpenStart = 0; + mReopenThread = 0; + +#if HAVE_LIBSWSCALE + mConvertContext = NULL; #endif - /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ - if(colours == ZM_COLOUR_RGB32) { - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - imagePixFormat = AV_PIX_FMT_RGBA; - } else if(colours == ZM_COLOUR_RGB24) { - subpixelorder = ZM_SUBPIX_ORDER_RGB; - imagePixFormat = AV_PIX_FMT_RGB24; - } else if(colours == ZM_COLOUR_GRAY8) { - subpixelorder = ZM_SUBPIX_ORDER_NONE; - imagePixFormat = AV_PIX_FMT_GRAY8; - } else { - Panic("Unexpected colours: %d",colours); - } - + /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = AV_PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = AV_PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = AV_PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + } FfmpegCamera::~FfmpegCamera() { - CloseFfmpeg(); + CloseFfmpeg(); - if ( capture ) - { - Terminate(); - } + if ( capture ) + { + Terminate(); + } } void FfmpegCamera::Initialise() { - if ( logDebugging() ) - av_log_set_level( AV_LOG_DEBUG ); - else - av_log_set_level( AV_LOG_QUIET ); + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); - av_register_all(); + av_register_all(); } void FfmpegCamera::Terminate() @@ -101,373 +101,373 @@ void FfmpegCamera::Terminate() int FfmpegCamera::PrimeCapture() { - Info( "Priming capture from %s", mPath.c_str() ); + Info( "Priming capture from %s", mPath.c_str() ); - if (OpenFfmpeg() != 0){ - ReopenFfmpeg(); - } - return 0; + if (OpenFfmpeg() != 0){ + ReopenFfmpeg(); + } + return 0; } int FfmpegCamera::PreCapture() { - // Nothing to do here - return( 0 ); + // Nothing to do here + return( 0 ); } int FfmpegCamera::Capture( Image &image ) { - if (!mCanCapture){ - return -1; + if (!mCanCapture){ + return -1; + } + + // If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread. + if (mReopenThread != 0) { + void *retval = 0; + int ret; + + ret = pthread_join(mReopenThread, &retval); + if (ret != 0){ + Error("Could not join reopen thread."); } - // If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread. - if (mReopenThread != 0) { - void *retval = 0; - int ret; - - ret = pthread_join(mReopenThread, &retval); - if (ret != 0){ - Error("Could not join reopen thread."); - } - - Info( "Successfully reopened stream." ); - mReopenThread = 0; - } + Info( "Successfully reopened stream." ); + mReopenThread = 0; + } - AVPacket packet; - uint8_t* directbuffer; + AVPacket packet; + uint8_t* directbuffer; - /* Request a writeable buffer of the target image */ - directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); - if(directbuffer == NULL) { - Error("Failed requesting writeable buffer for the captured image."); - return (-1); - } - - int frameComplete = false; - while ( !frameComplete ) + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } + + int frameComplete = false; + while ( !frameComplete ) + { + int avResult = av_read_frame( mFormatContext, &packet ); + if ( avResult < 0 ) { - int avResult = av_read_frame( mFormatContext, &packet ); - if ( avResult < 0 ) - { - char errbuf[AV_ERROR_MAX_STRING_SIZE]; - av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE); - if ( - // Check if EOF. - (avResult == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) || - // Check for Connection failure. - (avResult == -110) - ) - { - Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf); - ReopenFfmpeg(); - } + char errbuf[AV_ERROR_MAX_STRING_SIZE]; + av_strerror(avResult, errbuf, AV_ERROR_MAX_STRING_SIZE); + if ( + // Check if EOF. + (avResult == AVERROR_EOF || (mFormatContext->pb && mFormatContext->pb->eof_reached)) || + // Check for Connection failure. + (avResult == -110) + ) + { + Info( "av_read_frame returned \"%s\". Reopening stream.", errbuf); + ReopenFfmpeg(); + } - Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf ); - return( -1 ); - } - Debug( 5, "Got packet from stream %d", packet.stream_index ); - if ( packet.stream_index == mVideoStreamId ) - { + Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, avResult, errbuf ); + return( -1 ); + } + Debug( 5, "Got packet from stream %d", packet.stream_index ); + if ( packet.stream_index == mVideoStreamId ) + { #if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0) - if ( avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ) < 0 ) + if ( avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ) < 0 ) #else - if ( avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size ) < 0 ) + if ( avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size ) < 0 ) #endif - Fatal( "Unable to decode frame at frame %d", frameCount ); + Fatal( "Unable to decode frame at frame %d", frameCount ); - Debug( 4, "Decoded video packet at frame %d", frameCount ); + Debug( 4, "Decoded video packet at frame %d", frameCount ); - if ( frameComplete ) - { - Debug( 3, "Got frame %d", frameCount ); + if ( frameComplete ) + { + Debug( 3, "Got frame %d", frameCount ); - avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); - + avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); + #if HAVE_LIBSWSCALE - if(mConvertContext == NULL) { - mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); + if(mConvertContext == NULL) { + mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); - if(mConvertContext == NULL) - Fatal( "Unable to create conversion context for %s", mPath.c_str() ); - } - - if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) - Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount ); + if(mConvertContext == NULL) + Fatal( "Unable to create conversion context for %s", mPath.c_str() ); + } + + if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) + Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount ); #else // HAVE_LIBSWSCALE - Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); + Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); #endif // HAVE_LIBSWSCALE - frameCount++; - } - } -#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) - av_packet_unref( &packet); -#else - av_free_packet( &packet ); -#endif + frameCount++; + } } - return (0); +#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) + av_packet_unref( &packet); +#else + av_free_packet( &packet ); +#endif + } + return (0); } int FfmpegCamera::PostCapture() { - // Nothing to do here - return( 0 ); + // Nothing to do here + return( 0 ); } int FfmpegCamera::OpenFfmpeg() { - Debug ( 2, "OpenFfmpeg called." ); + Debug ( 2, "OpenFfmpeg called." ); - mOpenStart = time(NULL); - mIsOpening = true; + mOpenStart = time(NULL); + mIsOpening = true; - // Open the input, not necessarily a file + // Open the input, not necessarily a file #if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0) - Debug ( 1, "Calling av_open_input_file" ); - if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) !=0 ) + Debug ( 1, "Calling av_open_input_file" ); + if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) !=0 ) #else - // Handle options - AVDictionary *opts = 0; - StringVector opVect = split(Options(), ","); - - // Set transport method as specified by method field, rtpUni is default - if ( Method() == "rtpMulti" ) - opVect.push_back("rtsp_transport=udp_multicast"); - else if ( Method() == "rtpRtsp" ) - opVect.push_back("rtsp_transport=tcp"); - else if ( Method() == "rtpRtspHttp" ) - opVect.push_back("rtsp_transport=http"); - - Debug(2, "Number of Options: %d",opVect.size()); - for (size_t i=0; i 1) { - parts[0] = trimSpaces(parts[0]); - parts[1] = trimSpaces(parts[1]); - if ( av_dict_set(&opts, parts[0].c_str(), parts[1].c_str(), 0) == 0 ) { - Debug(2, "set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str()); - } - else - { - Warning( "Error trying to set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str() ); - } - - } - else - { - Warning( "Unable to parse ffmpeg option %d '%s', expecting key=value", i, opVect[i].c_str() ); - } - } - Debug ( 1, "Calling avformat_open_input" ); + // Handle options + AVDictionary *opts = 0; + StringVector opVect = split(Options(), ","); + + // Set transport method as specified by method field, rtpUni is default + if ( Method() == "rtpMulti" ) + opVect.push_back("rtsp_transport=udp_multicast"); + else if ( Method() == "rtpRtsp" ) + opVect.push_back("rtsp_transport=tcp"); + else if ( Method() == "rtpRtspHttp" ) + opVect.push_back("rtsp_transport=http"); + + Debug(2, "Number of Options: %d",opVect.size()); + for (size_t i=0; i 1) { + parts[0] = trimSpaces(parts[0]); + parts[1] = trimSpaces(parts[1]); + if ( av_dict_set(&opts, parts[0].c_str(), parts[1].c_str(), 0) == 0 ) { + Debug(2, "set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str()); + } + else + { + Warning( "Error trying to set option %d '%s' to '%s'", i, parts[0].c_str(), parts[1].c_str() ); + } + + } + else + { + Warning( "Unable to parse ffmpeg option %d '%s', expecting key=value", i, opVect[i].c_str() ); + } + } + Debug ( 1, "Calling avformat_open_input" ); - mFormatContext = avformat_alloc_context( ); - mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback; - mFormatContext->interrupt_callback.opaque = this; + mFormatContext = avformat_alloc_context( ); + mFormatContext->interrupt_callback.callback = FfmpegInterruptCallback; + mFormatContext->interrupt_callback.opaque = this; - if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) !=0 ) + if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, &opts ) !=0 ) #endif - { - mIsOpening = false; - Error( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) ); - return -1; - } - - AVDictionaryEntry *e; - if ((e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL) { - Warning( "Option %s not recognized by ffmpeg", e->key); - } - + { mIsOpening = false; - Debug ( 1, "Opened input" ); + Error( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) ); + return -1; + } - // Locate stream info from avformat_open_input + AVDictionaryEntry *e; + if ((e = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX)) != NULL) { + Warning( "Option %s not recognized by ffmpeg", e->key); + } + + mIsOpening = false; + Debug ( 1, "Opened input" ); + + // Locate stream info from avformat_open_input #if !LIBAVFORMAT_VERSION_CHECK(53, 6, 0, 6, 0) - Debug ( 1, "Calling av_find_stream_info" ); - if ( av_find_stream_info( mFormatContext ) < 0 ) + Debug ( 1, "Calling av_find_stream_info" ); + if ( av_find_stream_info( mFormatContext ) < 0 ) #else - Debug ( 1, "Calling avformat_find_stream_info" ); - if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 ) + Debug ( 1, "Calling avformat_find_stream_info" ); + if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 ) #endif - Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) ); + Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) ); - Debug ( 1, "Got stream info" ); + Debug ( 1, "Got stream info" ); - // Find first video stream present - mVideoStreamId = -1; - for (unsigned int i=0; i < mFormatContext->nb_streams; i++ ) - { + // Find first video stream present + mVideoStreamId = -1; + for (unsigned int i=0; i < mFormatContext->nb_streams; i++ ) + { #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) + if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) #else - if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) + if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) #endif - { - mVideoStreamId = i; - break; - } + { + mVideoStreamId = i; + break; } - if ( mVideoStreamId == -1 ) - Fatal( "Unable to locate video stream in %s", mPath.c_str() ); + } + if ( mVideoStreamId == -1 ) + Fatal( "Unable to locate video stream in %s", mPath.c_str() ); - Debug ( 1, "Found video stream" ); + Debug ( 1, "Found video stream" ); - mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; + mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; - // Try and get the codec from the codec context - if ( (mCodec = avcodec_find_decoder( mCodecContext->codec_id )) == NULL ) - Fatal( "Can't find codec for video stream from %s", mPath.c_str() ); + // Try and get the codec from the codec context + if ( (mCodec = avcodec_find_decoder( mCodecContext->codec_id )) == NULL ) + Fatal( "Can't find codec for video stream from %s", mPath.c_str() ); - Debug ( 1, "Found decoder" ); + Debug ( 1, "Found decoder" ); - // Open the codec + // Open the codec #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) - Debug ( 1, "Calling avcodec_open" ); - if ( avcodec_open( mCodecContext, mCodec ) < 0 ) + Debug ( 1, "Calling avcodec_open" ); + if ( avcodec_open( mCodecContext, mCodec ) < 0 ) #else - Debug ( 1, "Calling avcodec_open2" ); - if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) + Debug ( 1, "Calling avcodec_open2" ); + if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) #endif - Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); + Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); - Debug ( 1, "Opened codec" ); + Debug ( 1, "Opened codec" ); - // Allocate space for the native video frame + // Allocate space for the native video frame #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - mRawFrame = av_frame_alloc(); + mRawFrame = av_frame_alloc(); #else - mRawFrame = avcodec_alloc_frame(); + mRawFrame = avcodec_alloc_frame(); #endif - // Allocate space for the converted video frame + // Allocate space for the converted video frame #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - mFrame = av_frame_alloc(); + mFrame = av_frame_alloc(); #else - mFrame = avcodec_alloc_frame(); + mFrame = avcodec_alloc_frame(); #endif - if(mRawFrame == NULL || mFrame == NULL) - Fatal( "Unable to allocate frame for %s", mPath.c_str() ); + if(mRawFrame == NULL || mFrame == NULL) + Fatal( "Unable to allocate frame for %s", mPath.c_str() ); - Debug ( 1, "Allocated frames" ); - - int pSize = avpicture_get_size( imagePixFormat, width, height ); - if( (unsigned int)pSize != imagesize) { - Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); - } + Debug ( 1, "Allocated frames" ); + + int pSize = avpicture_get_size( imagePixFormat, width, height ); + if( (unsigned int)pSize != imagesize) { + Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); + } - Debug ( 1, "Validated imagesize" ); - + Debug ( 1, "Validated imagesize" ); + #if HAVE_LIBSWSCALE - Debug ( 1, "Calling sws_isSupportedInput" ); - if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { - Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); - } - - if(!sws_isSupportedOutput(imagePixFormat)) { - Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); - } - + Debug ( 1, "Calling sws_isSupportedInput" ); + if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { + Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); + } + + if(!sws_isSupportedOutput(imagePixFormat)) { + Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); + } + #else // HAVE_LIBSWSCALE - Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); + Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); #endif // HAVE_LIBSWSCALE - mCanCapture = true; + mCanCapture = true; - return 0; + return 0; } int FfmpegCamera::ReopenFfmpeg() { - Debug(2, "ReopenFfmpeg called."); + Debug(2, "ReopenFfmpeg called."); - mCanCapture = false; - if (pthread_create( &mReopenThread, NULL, ReopenFfmpegThreadCallback, (void*) this) != 0){ - // Log a fatal error and exit the process. - Fatal( "ReopenFfmpeg failed to create worker thread." ); - } + mCanCapture = false; + if (pthread_create( &mReopenThread, NULL, ReopenFfmpegThreadCallback, (void*) this) != 0){ + // Log a fatal error and exit the process. + Fatal( "ReopenFfmpeg failed to create worker thread." ); + } - return 0; + return 0; } int FfmpegCamera::CloseFfmpeg(){ - Debug(2, "CloseFfmpeg called."); + Debug(2, "CloseFfmpeg called."); - mCanCapture = false; + mCanCapture = false; #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &mFrame ); - av_frame_free( &mRawFrame ); + av_frame_free( &mFrame ); + av_frame_free( &mRawFrame ); #else - av_freep( &mFrame ); - av_freep( &mRawFrame ); + av_freep( &mFrame ); + av_freep( &mRawFrame ); #endif - + #if HAVE_LIBSWSCALE - if ( mConvertContext ) - { - sws_freeContext( mConvertContext ); - mConvertContext = NULL; - } + if ( mConvertContext ) + { + sws_freeContext( mConvertContext ); + mConvertContext = NULL; + } #endif - if ( mCodecContext ) - { - avcodec_close( mCodecContext ); - mCodecContext = NULL; // Freed by av_close_input_file - } - if ( mFormatContext ) - { + if ( mCodecContext ) + { + avcodec_close( mCodecContext ); + mCodecContext = NULL; // Freed by av_close_input_file + } + if ( mFormatContext ) + { #if !LIBAVFORMAT_VERSION_CHECK(53, 17, 0, 25, 0) - av_close_input_file( mFormatContext ); + av_close_input_file( mFormatContext ); #else - avformat_close_input( &mFormatContext ); + avformat_close_input( &mFormatContext ); #endif - mFormatContext = NULL; - } + mFormatContext = NULL; + } - return 0; + return 0; } int FfmpegCamera::FfmpegInterruptCallback(void *ctx) { - FfmpegCamera* camera = reinterpret_cast(ctx); - if (camera->mIsOpening){ - int now = time(NULL); - if ((now - camera->mOpenStart) > config.ffmpeg_open_timeout) { - Error ( "Open video took more than %d seconds.", config.ffmpeg_open_timeout ); - return 1; - } + FfmpegCamera* camera = reinterpret_cast(ctx); + if (camera->mIsOpening){ + int now = time(NULL); + if ((now - camera->mOpenStart) > config.ffmpeg_open_timeout) { + Error ( "Open video took more than %d seconds.", config.ffmpeg_open_timeout ); + return 1; } + } - return 0; + return 0; } void *FfmpegCamera::ReopenFfmpegThreadCallback(void *ctx){ - if (ctx == NULL) return NULL; + if (ctx == NULL) return NULL; - FfmpegCamera* camera = reinterpret_cast(ctx); + FfmpegCamera* camera = reinterpret_cast(ctx); - while (1){ - // Close current stream. - camera->CloseFfmpeg(); + while (1){ + // Close current stream. + camera->CloseFfmpeg(); - // Sleep if necessary to not reconnect too fast. - int wait = config.ffmpeg_open_timeout - (time(NULL) - camera->mOpenStart); - wait = wait < 0 ? 0 : wait; - if (wait > 0){ - Debug( 1, "Sleeping %d seconds before reopening stream.", wait ); - sleep(wait); - } - - if (camera->OpenFfmpeg() == 0){ - return NULL; - } + // Sleep if necessary to not reconnect too fast. + int wait = config.ffmpeg_open_timeout - (time(NULL) - camera->mOpenStart); + wait = wait < 0 ? 0 : wait; + if (wait > 0){ + Debug( 1, "Sleeping %d seconds before reopening stream.", wait ); + sleep(wait); } + + if (camera->OpenFfmpeg() == 0){ + return NULL; + } + } } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_ffmpeg_camera.h b/src/zm_ffmpeg_camera.h index ff3ee5d1d..a8ed2a6a6 100644 --- a/src/zm_ffmpeg_camera.h +++ b/src/zm_ffmpeg_camera.h @@ -33,51 +33,51 @@ class FfmpegCamera : public Camera { protected: - std::string mPath; - std::string mMethod; - std::string mOptions; + std::string mPath; + std::string mMethod; + std::string mOptions; - int frameCount; + int frameCount; #if HAVE_LIBAVFORMAT - AVFormatContext *mFormatContext; - int mVideoStreamId; - AVCodecContext *mCodecContext; - AVCodec *mCodec; - AVFrame *mRawFrame; - AVFrame *mFrame; - _AVPIXELFORMAT imagePixFormat; + AVFormatContext *mFormatContext; + int mVideoStreamId; + AVCodecContext *mCodecContext; + AVCodec *mCodec; + AVFrame *mRawFrame; + AVFrame *mFrame; + _AVPIXELFORMAT imagePixFormat; - int OpenFfmpeg(); - int ReopenFfmpeg(); - int CloseFfmpeg(); - static int FfmpegInterruptCallback(void *ctx); - static void* ReopenFfmpegThreadCallback(void *ctx); - bool mIsOpening; - bool mCanCapture; - int mOpenStart; - pthread_t mReopenThread; + int OpenFfmpeg(); + int ReopenFfmpeg(); + int CloseFfmpeg(); + static int FfmpegInterruptCallback(void *ctx); + static void* ReopenFfmpegThreadCallback(void *ctx); + bool mIsOpening; + bool mCanCapture; + int mOpenStart; + pthread_t mReopenThread; #endif // HAVE_LIBAVFORMAT #if HAVE_LIBSWSCALE - struct SwsContext *mConvertContext; + struct SwsContext *mConvertContext; #endif public: - FfmpegCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - ~FfmpegCamera(); + FfmpegCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~FfmpegCamera(); - const std::string &Path() const { return( mPath ); } - const std::string &Options() const { return( mOptions ); } - const std::string &Method() const { return( mMethod ); } + const std::string &Path() const { return( mPath ); } + const std::string &Options() const { return( mOptions ); } + const std::string &Method() const { return( mMethod ); } - void Initialise(); - void Terminate(); + void Initialise(); + void Terminate(); - int PrimeCapture(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); }; #endif // ZM_FFMPEG_CAMERA_H diff --git a/src/zm_file_camera.cpp b/src/zm_file_camera.cpp index 28ce2b155..4292cea48 100644 --- a/src/zm_file_camera.cpp +++ b/src/zm_file_camera.cpp @@ -36,28 +36,28 @@ FileCamera::FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : Camera( p_id, FILE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ) { - strncpy( path, p_path, sizeof(path) ); - if ( capture ) - { - Initialise(); - } + strncpy( path, p_path, sizeof(path) ); + if ( capture ) + { + Initialise(); + } } FileCamera::~FileCamera() { - if ( capture ) - { - Terminate(); - } + if ( capture ) + { + Terminate(); + } } void FileCamera::Initialise() { - if ( !path[0] ) - { - Error( "No path specified for file image" ); - exit( -1 ); - } + if ( !path[0] ) + { + Error( "No path specified for file image" ); + exit( -1 ); + } } void FileCamera::Terminate() @@ -66,26 +66,26 @@ void FileCamera::Terminate() int FileCamera::PreCapture() { - struct stat statbuf; - if ( stat( path, &statbuf ) < 0 ) - { - Error( "Can't stat %s: %s", path, strerror(errno) ); - return( -1 ); - } + struct stat statbuf; + if ( stat( path, &statbuf ) < 0 ) + { + Error( "Can't stat %s: %s", path, strerror(errno) ); + return( -1 ); + } - while ( (time( 0 ) - statbuf.st_mtime) < 1 ) - { - usleep( 100000 ); - } - return( 0 ); + while ( (time( 0 ) - statbuf.st_mtime) < 1 ) + { + usleep( 100000 ); + } + return( 0 ); } int FileCamera::Capture( Image &image ) { - return( image.ReadJpeg( path, colours, subpixelorder )?0:-1 ); + return( image.ReadJpeg( path, colours, subpixelorder )?0:-1 ); } int FileCamera::PostCapture() { - return( 0 ); + return( 0 ); } diff --git a/src/zm_file_camera.h b/src/zm_file_camera.h index 2afdbc1f2..19e5971b8 100644 --- a/src/zm_file_camera.h +++ b/src/zm_file_camera.h @@ -33,19 +33,19 @@ class FileCamera : public Camera { protected: - char path[PATH_MAX]; + char path[PATH_MAX]; public: - FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - ~FileCamera(); + FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~FileCamera(); - const char *Path() const { return( path ); } + const char *Path() const { return( path ); } - void Initialise(); - void Terminate(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + void Initialise(); + void Terminate(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); }; #endif // ZM_FILE_CAMERA_H diff --git a/src/zm_font.h b/src/zm_font.h index 844ff4f1e..cdad72dc4 100644 --- a/src/zm_font.h +++ b/src/zm_font.h @@ -1,3337 +1,3337 @@ /**********************************************/ -/* */ -/* Font file generated by rthelen */ -/* */ +/* */ +/* Font file generated by rthelen */ +/* */ /**********************************************/ static unsigned char fontdata[] = { - /* 0 0x00 '^A' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 1 0x01 '^B' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 2 0x02 '^C' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 3 0x03 '^D' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 4 0x04 '^E' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 5 0x05 '^F' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 6 0x06 '^G' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 7 0x07 '^H' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 8 0x08 '^I' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 9 0x09 '^J' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 10 0x0a '^K' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 11 0x0b '^L' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 12 0x0c '^M' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 13 0x0d '^N' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 14 0x0e '^O' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 15 0x0f '^P' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 16 0x10 '^Q' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 17 0x11 '^R' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x54, /* 0 0 0 00 */ - 0x38, /* 00 000 */ - 0x54, /* 0 0 0 00 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 18 0x12 '^S' */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x50, /* 0 0 0000 */ - 0x50, /* 0 0 0000 */ - 0x20, /* 00 00000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 19 0x13 '^T' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x7c, /* 0 00 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 20 0x14 '^U' */ - 0x18, /* 000 000 */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x7c, /* 0 00 */ - 0x78, /* 0 000 */ - 0x78, /* 0 000 */ - 0x7c, /* 0 00 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 21 0x15 '^V' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 22 0x16 '^W' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 23 0x17 '^X' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 24 0x18 '^Y' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 25 0x19 '^Z' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 26 0x1a '^[' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 27 0x1b '^\' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 28 0x1c '^]' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 29 0x1d '^^' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 30 0x1e '^_' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 31 0x1f '^`' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 32 0x20 ' ' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 33 0x21 '!' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 34 0x22 '"' */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 35 0x23 '#' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x7c, /* 0 00 */ - 0x28, /* 00 0 000 */ - 0x7c, /* 0 00 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 36 0x24 '$' */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x54, /* 0 0 0 00 */ - 0x50, /* 0 0 0000 */ - 0x38, /* 00 000 */ - 0x14, /* 000 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 37 0x25 '%' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x58, /* 0 0 000 */ - 0x28, /* 00 0 000 */ - 0x34, /* 00 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x48, /* 0 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 38 0x26 '&' */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x48, /* 0 00 000 */ - 0x50, /* 0 0 0000 */ - 0x20, /* 00 00000 */ - 0x54, /* 0 0 0 00 */ - 0x48, /* 0 00 000 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 39 0x27 ''' */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 40 0x28 '(' */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x04, /* 00000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 41 0x29 ')' */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 42 0x2a '*' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x54, /* 0 0 0 00 */ - 0x38, /* 00 000 */ - 0x54, /* 0 0 0 00 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 43 0x2b '+' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x7c, /* 0 00 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 44 0x2c ',' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x30, /* 00 0000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - - /* 45 0x2d '-' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 46 0x2e '.' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 000 000 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 47 0x2f '/' */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x20, /* 00 00000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - - /* 48 0x30 '0' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x64, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 49 0x31 '1' */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x18, /* 000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x1c, /* 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 50 0x32 '2' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 51 0x33 '3' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x04, /* 00000 00 */ - 0x18, /* 000 000 */ - 0x04, /* 00000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 52 0x34 '4' */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x18, /* 000 000 */ - 0x28, /* 00 0 000 */ - 0x48, /* 0 00 000 */ - 0x7c, /* 0 00 */ - 0x08, /* 0000 000 */ - 0x1c, /* 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 53 0x35 '5' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 54 0x36 '6' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 55 0x37 '7' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 56 0x38 '8' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 57 0x39 '9' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x3c, /* 00 00 */ - 0x04, /* 00000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 58 0x3a ':' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x18, /* 000 000 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x18, /* 000 000 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 59 0x3b ';' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x30, /* 00 0000 */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x30, /* 00 0000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - - /* 60 0x3c '<' */ - 0x00, /* 00000000 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x04, /* 00000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 61 0x3d '=' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 62 0x3e '>' */ - 0x00, /* 00000000 */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 63 0x3f '?' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 64 0x40 '@' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x74, /* 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x78, /* 0 000 */ - 0x40, /* 0 000000 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 65 0x41 'A' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 66 0x42 'B' */ - 0x00, /* 00000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 67 0x43 'C' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 68 0x44 'D' */ - 0x00, /* 00000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 69 0x45 'E' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 70 0x46 'F' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 71 0x47 'G' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x40, /* 0 000000 */ - 0x4c, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 72 0x48 'H' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 73 0x49 'I' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 74 0x4a 'J' */ - 0x00, /* 00000000 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 75 0x4b 'K' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x48, /* 0 00 000 */ - 0x50, /* 0 0 0000 */ - 0x60, /* 0 00000 */ - 0x50, /* 0 0 0000 */ - 0x48, /* 0 00 000 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 76 0x4c 'L' */ - 0x00, /* 00000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 77 0x4d 'M' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x6c, /* 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 78 0x4e 'N' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x64, /* 0 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x4c, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 79 0x4f 'O' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 80 0x50 'P' */ - 0x00, /* 00000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 81 0x51 'Q' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x54, /* 0 0 0 00 */ - 0x38, /* 00 000 */ - 0x04, /* 00000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 82 0x52 'R' */ - 0x00, /* 00000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 83 0x53 'S' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x40, /* 0 000000 */ - 0x38, /* 00 000 */ - 0x04, /* 00000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 84 0x54 'T' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 85 0x55 'U' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 86 0x56 'V' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 87 0x57 'W' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x6c, /* 0 0 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 88 0x58 'X' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 89 0x59 'Y' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 90 0x5a 'Z' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x40, /* 0 000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 91 0x5b '[' */ - 0x0c, /* 0000 00 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x0c, /* 0000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 92 0x5c '\' */ - 0x20, /* 00 00000 */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x02, /* 000000 0 */ - 0x02, /* 000000 0 */ - 0x00, /* 00000000 */ - - /* 93 0x5d ']' */ - 0x30, /* 00 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x30, /* 00 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 94 0x5e '^' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 95 0x5f '_' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 96 0x60 '`' */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 97 0x61 'a' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 98 0x62 'b' */ - 0x00, /* 00000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 99 0x63 'c' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x40, /* 0 000000 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 100 0x64 'd' */ - 0x00, /* 00000000 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 101 0x65 'e' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 102 0x66 'f' */ - 0x00, /* 00000000 */ - 0x0c, /* 0000 00 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 103 0x67 'g' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x3c, /* 00 00 */ - 0x04, /* 00000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - - /* 104 0x68 'h' */ - 0x00, /* 00000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 105 0x69 'i' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 106 0x6a 'j' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x60, /* 0 00000 */ - 0x00, /* 00000000 */ - - /* 107 0x6b 'k' */ - 0x00, /* 00000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x48, /* 0 00 000 */ - 0x50, /* 0 0 0000 */ - 0x70, /* 0 0000 */ - 0x48, /* 0 00 000 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 108 0x6c 'l' */ - 0x00, /* 00000000 */ - 0x30, /* 00 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 109 0x6d 'm' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x78, /* 0 000 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 110 0x6e 'n' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x58, /* 0 0 000 */ - 0x64, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 111 0x6f 'o' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 112 0x70 'p' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x78, /* 0 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - - /* 113 0x71 'q' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x3c, /* 00 00 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x00, /* 00000000 */ - - /* 114 0x72 'r' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x58, /* 0 0 000 */ - 0x64, /* 0 00 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 115 0x73 's' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x40, /* 0 000000 */ - 0x38, /* 00 000 */ - 0x04, /* 00000 00 */ - 0x78, /* 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 116 0x74 't' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x0c, /* 0000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 117 0x75 'u' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 118 0x76 'v' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 119 0x77 'w' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 120 0x78 'x' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 121 0x79 'y' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x3c, /* 00 00 */ - 0x04, /* 00000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - - /* 122 0x7a 'z' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 123 0x7b '{' */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x04, /* 00000 00 */ - 0x00, /* 00000000 */ - - /* 124 0x7c '|' */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 125 0x7d '}' */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - - /* 126 0x7e '~' */ - 0x00, /* 00000000 */ - 0x34, /* 00 0 00 */ - 0x58, /* 0 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 127 0x7f '^?' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 128 0x80 '\200' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 129 0x81 '\201' */ - 0x28, /* 00 0 000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 130 0x82 '\202' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 131 0x83 '\203' */ - 0x10, /* 000 0000 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x78, /* 0 000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 132 0x84 '\204' */ - 0x58, /* 0 0 000 */ - 0x44, /* 0 000 00 */ - 0x64, /* 0 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x4c, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 133 0x85 '\205' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 134 0x86 '\206' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 135 0x87 '\207' */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 136 0x88 '\210' */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 137 0x89 '\211' */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 138 0x8a '\212' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 139 0x8b '\213' */ - 0x34, /* 00 0 00 */ - 0x58, /* 0 0 000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 140 0x8c '\214' */ - 0x18, /* 000 000 */ - 0x24, /* 00 00 00 */ - 0x18, /* 000 000 */ - 0x3c, /* 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 141 0x8d '\215' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x3c, /* 00 00 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - - /* 142 0x8e '\216' */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 143 0x8f '\217' */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 144 0x90 '\220' */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 145 0x91 '\221' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x40, /* 0 000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 146 0x92 '\222' */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 147 0x93 '\223' */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 148 0x94 '\224' */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 149 0x95 '\225' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 150 0x96 '\226' */ - 0x34, /* 00 0 00 */ - 0x58, /* 0 0 000 */ - 0x00, /* 00000000 */ - 0x58, /* 0 0 000 */ - 0x64, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 151 0x97 '\227' */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 152 0x98 '\230' */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 153 0x99 '\231' */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 154 0x9a '\232' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 155 0x9b '\233' */ - 0x34, /* 00 0 00 */ - 0x58, /* 0 0 000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 156 0x9c '\234' */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 157 0x9d '\235' */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 158 0x9e '\236' */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 159 0x9f '\237' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x34, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 160 0xa0 '\240' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 161 0xa1 '\241' */ - 0x18, /* 000 000 */ - 0x24, /* 00 00 00 */ - 0x24, /* 00 00 00 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 162 0xa2 '\242' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x54, /* 0 0 0 00 */ - 0x50, /* 0 0 0000 */ - 0x54, /* 0 0 0 00 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 163 0xa3 '\243' */ - 0x30, /* 00 0000 */ - 0x48, /* 0 00 000 */ - 0x40, /* 0 000000 */ - 0x70, /* 0 0000 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x44, /* 0 000 00 */ - 0x78, /* 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 164 0xa4 '\244' */ - 0x44, /* 0 000 00 */ - 0x24, /* 00 00 00 */ - 0x50, /* 0 0 0000 */ - 0x48, /* 0 00 000 */ - 0x24, /* 00 00 00 */ - 0x14, /* 000 0 00 */ - 0x48, /* 0 00 000 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 165 0xa5 '\245' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x7c, /* 0 00 */ - 0x7c, /* 0 00 */ - 0x7c, /* 0 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 166 0xa6 '\246' */ - 0x3c, /* 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x3c, /* 00 00 */ - 0x14, /* 000 0 00 */ - 0x14, /* 000 0 00 */ - 0x14, /* 000 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 167 0xa7 '\247' */ - 0x18, /* 000 000 */ - 0x24, /* 00 00 00 */ - 0x44, /* 0 000 00 */ - 0x48, /* 0 00 000 */ - 0x48, /* 0 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x58, /* 0 0 000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 168 0xa8 '\250' */ - 0x00, /* 00000000 */ - 0x70, /* 0 0000 */ - 0x08, /* 0000 000 */ - 0x64, /* 0 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x64, /* 0 00 00 */ - 0x58, /* 0 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 169 0xa9 '\251' */ - 0x00, /* 00000000 */ - 0x70, /* 0 0000 */ - 0x08, /* 0000 000 */ - 0x34, /* 00 0 00 */ - 0x44, /* 0 000 00 */ - 0x34, /* 00 0 00 */ - 0x08, /* 0000 000 */ - 0x70, /* 0 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 170 0xaa '\252' */ - 0x00, /* 00000000 */ - 0x7a, /* 0 0 0 */ - 0x2e, /* 00 0 0 */ - 0x2e, /* 00 0 0 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 171 0xab '\253' */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 172 0xac '\254' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 173 0xad '\255' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x7c, /* 0 00 */ - 0x10, /* 000 0000 */ - 0x7c, /* 0 00 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 174 0xae '\256' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x50, /* 0 0 0000 */ - 0x50, /* 0 0 0000 */ - 0x78, /* 0 000 */ - 0x50, /* 0 0 0000 */ - 0x50, /* 0 0 0000 */ - 0x5c, /* 0 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 175 0xaf '\257' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x4c, /* 0 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x64, /* 0 00 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 176 0xb0 '\260' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x6c, /* 0 0 00 */ - 0x54, /* 0 0 0 00 */ - 0x6c, /* 0 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 177 0xb1 '\261' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x7c, /* 0 00 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 178 0xb2 '\262' */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 179 0xb3 '\263' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x04, /* 00000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x1c, /* 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 180 0xb4 '\264' */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x7c, /* 0 00 */ - 0x10, /* 000 0000 */ - 0x7c, /* 0 00 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 181 0xb5 '\265' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x48, /* 0 00 000 */ - 0x48, /* 0 00 000 */ - 0x48, /* 0 00 000 */ - 0x48, /* 0 00 000 */ - 0x74, /* 0 0 00 */ - 0x40, /* 0 000000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - - /* 182 0xb6 '\266' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x0c, /* 0000 00 */ - 0x14, /* 000 0 00 */ - 0x24, /* 00 00 00 */ - 0x24, /* 00 00 00 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 183 0xb7 '\267' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x24, /* 00 00 00 */ - 0x10, /* 000 0000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x24, /* 00 00 00 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 184 0xb8 '\270' */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 185 0xb9 '\271' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 186 0xba '\272' */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x60, /* 0 00000 */ - 0x00, /* 00000000 */ - - /* 187 0xbb '\273' */ - 0x00, /* 00000000 */ - 0x1c, /* 000 00 */ - 0x24, /* 00 00 00 */ - 0x24, /* 00 00 00 */ - 0x1c, /* 000 00 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 188 0xbc '\274' */ - 0x00, /* 00000000 */ - 0x18, /* 000 000 */ - 0x24, /* 00 00 00 */ - 0x24, /* 00 00 00 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 189 0xbd '\275' */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x6c, /* 0 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 190 0xbe '\276' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x54, /* 0 0 0 00 */ - 0x5c, /* 0 0 00 */ - 0x50, /* 0 0 0000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 191 0xbf '\277' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x4c, /* 0 00 00 */ - 0x54, /* 0 0 0 00 */ - 0x64, /* 0 00 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 192 0xc0 '\300' */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x20, /* 00 00000 */ - 0x40, /* 0 000000 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 193 0xc1 '\301' */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x08, /* 0000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 194 0xc2 '\302' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x04, /* 00000 00 */ - 0x04, /* 00000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 195 0xc3 '\303' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x0c, /* 0000 00 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x50, /* 0 0 0000 */ - 0x20, /* 00 00000 */ - 0x20, /* 00 00000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 196 0xc4 '\304' */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x60, /* 0 00000 */ - 0x00, /* 00000000 */ - - /* 197 0xc5 '\305' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x04, /* 00000 00 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x40, /* 0 000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 198 0xc6 '\306' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 199 0xc7 '\307' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x24, /* 00 00 00 */ - 0x48, /* 0 00 000 */ - 0x48, /* 0 00 000 */ - 0x24, /* 00 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 200 0xc8 '\310' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x48, /* 0 00 000 */ - 0x24, /* 00 00 00 */ - 0x24, /* 00 00 00 */ - 0x48, /* 0 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 201 0xc9 '\311' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x54, /* 0 0 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 202 0xca '\312' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 203 0xcb '\313' */ - 0x10, /* 000 0000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 204 0xcc '\314' */ - 0x58, /* 0 0 000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x7c, /* 0 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 205 0xcd '\315' */ - 0x58, /* 0 0 000 */ - 0x38, /* 00 000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 206 0xce '\316' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x50, /* 0 0 0000 */ - 0x50, /* 0 0 0000 */ - 0x58, /* 0 0 000 */ - 0x50, /* 0 0 0000 */ - 0x50, /* 0 0 0000 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 207 0xcf '\317' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x54, /* 0 0 0 00 */ - 0x5c, /* 0 0 00 */ - 0x50, /* 0 0 0000 */ - 0x2c, /* 00 0 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 208 0xd0 '\320' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 209 0xd1 '\321' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 210 0xd2 '\322' */ - 0x00, /* 00000000 */ - 0x14, /* 000 0 00 */ - 0x28, /* 00 0 000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 211 0xd3 '\323' */ - 0x00, /* 00000000 */ - 0x14, /* 000 0 00 */ - 0x14, /* 000 0 00 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 212 0xd4 '\324' */ - 0x00, /* 00000000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x18, /* 000 000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 213 0xd5 '\325' */ - 0x00, /* 00000000 */ - 0x18, /* 000 000 */ - 0x08, /* 0000 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 214 0xd6 '\326' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x7c, /* 0 00 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 215 0xd7 '\327' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x10, /* 000 0000 */ - 0x28, /* 00 0 000 */ - 0x44, /* 0 000 00 */ - 0x28, /* 00 0 000 */ - 0x10, /* 000 0000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 216 0xd8 '\330' */ - 0x00, /* 00000000 */ - 0x28, /* 00 0 000 */ - 0x00, /* 00000000 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x44, /* 0 000 00 */ - 0x3c, /* 00 00 */ - 0x04, /* 00000 00 */ - 0x38, /* 00 000 */ - 0x00, /* 00000000 */ - - /* 217 0xd9 '\331' */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ - 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ - 0x00, /* 00000000 */ - 0x7e, /* 0 0 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 218 0xda '\332' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 219 0xdb '\333' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 220 0xdc '\334' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 221 0xdd '\335' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 222 0xde '\336' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 223 0xdf '\337' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 224 0xe0 '\340' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 225 0xe1 '\341' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 226 0xe2 '\342' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 227 0xe3 '\343' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 228 0xe4 '\344' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 229 0xe5 '\345' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 230 0xe6 '\346' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 231 0xe7 '\347' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 232 0xe8 '\350' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 233 0xe9 '\351' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 234 0xea '\352' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 235 0xeb '\353' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 236 0xec '\354' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 237 0xed '\355' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 238 0xee '\356' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 239 0xef '\357' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 240 0xf0 '\360' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 241 0xf1 '\361' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 242 0xf2 '\362' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 243 0xf3 '\363' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 244 0xf4 '\364' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 245 0xf5 '\365' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 246 0xf6 '\366' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 247 0xf7 '\367' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 248 0xf8 '\370' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 249 0xf9 '\371' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 250 0xfa '\372' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 251 0xfb '\373' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 252 0xfc '\374' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 253 0xfd '\375' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 254 0xfe '\376' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - - /* 255 0xff '\377' */ - 0x00, /* 00000000 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x3c, /* 00 00 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ - 0x00, /* 00000000 */ + /* 0 0x00 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^G' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^H' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 9 0x09 '^J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^K' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 11 0x0b '^L' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^M' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^O' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^P' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^Q' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^S' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^U' */ + 0x18, /* 000 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x78, /* 0 000 */ + 0x78, /* 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^V' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^W' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^X' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^Y' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Z' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^[' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^\' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^]' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^^' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^_' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^`' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x38, /* 00 000 */ + 0x14, /* 000 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x58, /* 0 0 000 */ + 0x28, /* 00 0 000 */ + 0x34, /* 00 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x18, /* 000 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x28, /* 00 0 000 */ + 0x48, /* 0 00 000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x74, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x60, /* 0 00000 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x02, /* 000000 0 */ + 0x02, /* 000000 0 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x70, /* 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '^?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '\200' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '\201' */ + 0x28, /* 00 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '\202' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '\203' */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '\204' */ + 0x58, /* 0 0 000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '\205' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '\206' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '\207' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 '\210' */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '\211' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '\212' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '\213' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '\214' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '\215' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '\216' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '\217' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '\220' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '\221' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '\222' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '\223' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '\224' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '\225' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '\226' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '\227' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '\230' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '\231' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '\232' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '\233' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c '\234' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '\235' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e '\236' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f '\237' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 '\240' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '\241' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '\242' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '\243' */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x40, /* 0 000000 */ + 0x70, /* 0 0000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '\244' */ + 0x44, /* 0 000 00 */ + 0x24, /* 00 00 00 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x14, /* 000 0 00 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '\245' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '\246' */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x3c, /* 00 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '\247' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x58, /* 0 0 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '\250' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '\251' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x34, /* 00 0 00 */ + 0x44, /* 0 000 00 */ + 0x34, /* 00 0 00 */ + 0x08, /* 0000 000 */ + 0x70, /* 0 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '\252' */ + 0x00, /* 00000000 */ + 0x7a, /* 0 0 0 */ + 0x2e, /* 00 0 0 */ + 0x2e, /* 00 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '\253' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '\254' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '\255' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '\256' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x78, /* 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x5c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '\257' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '\260' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 177 0xb1 '\261' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 178 0xb2 '\262' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 179 0xb3 '\263' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 180 0xb4 '\264' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 181 0xb5 '\265' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x74, /* 0 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 182 0xb6 '\266' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x14, /* 000 0 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 183 0xb7 '\267' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x24, /* 00 00 00 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x24, /* 00 00 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 184 0xb8 '\270' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 185 0xb9 '\271' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 186 0xba '\272' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 187 0xbb '\273' */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 188 0xbc '\274' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '\275' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '\276' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '\277' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 192 0xc0 '\300' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '\301' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '\302' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 195 0xc3 '\303' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 196 0xc4 '\304' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '\305' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 198 0xc6 '\306' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 199 0xc7 '\307' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 200 0xc8 '\310' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '\311' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 202 0xca '\312' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '\313' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 204 0xcc '\314' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 205 0xcd '\315' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '\316' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x58, /* 0 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 207 0xcf '\317' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x2c, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '\320' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '\321' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 210 0xd2 '\322' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 211 0xd3 '\323' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '\324' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '\325' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 214 0xd6 '\326' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 215 0xd7 '\327' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 216 0xd8 '\330' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 217 0xd9 '\331' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '\332' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 219 0xdb '\333' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 220 0xdc '\334' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 221 0xdd '\335' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 222 0xde '\336' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 223 0xdf '\337' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 '\340' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 '\341' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 '\342' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 '\343' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 '\344' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 '\345' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 '\346' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 '\347' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 '\350' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 '\351' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea '\352' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb '\353' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec '\354' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed '\355' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee '\356' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef '\357' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '\360' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '\361' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '\362' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '\363' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '\364' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 245 0xf5 '\365' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 '\366' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '\367' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '\370' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '\371' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '\372' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '\373' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc '\374' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '\375' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '\376' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff '\377' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ }; diff --git a/src/zm_image.cpp b/src/zm_image.cpp index a302b4be5..d76384dc3 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -63,729 +63,729 @@ imgbufcpy_fptr_t fptr_imgbufcpy; Image::Image() { - if ( !initialised ) - Initialise(); - width = 0; - height = 0; - pixels = 0; - colours = 0; - subpixelorder = 0; - size = 0; - allocation = 0; - buffer = 0; - buffertype = 0; - holdbuffer = 0; - text[0] = '\0'; + if ( !initialised ) + Initialise(); + width = 0; + height = 0; + pixels = 0; + colours = 0; + subpixelorder = 0; + size = 0; + allocation = 0; + buffer = 0; + buffertype = 0; + holdbuffer = 0; + text[0] = '\0'; } Image::Image( const char *filename ) { - if ( !initialised ) - Initialise(); - width = 0; - height = 0; - pixels = 0; - colours = 0; - subpixelorder = 0; - size = 0; - allocation = 0; - buffer = 0; - buffertype = 0; - holdbuffer = 0; - ReadJpeg( filename, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB); - text[0] = '\0'; + if ( !initialised ) + Initialise(); + width = 0; + height = 0; + pixels = 0; + colours = 0; + subpixelorder = 0; + size = 0; + allocation = 0; + buffer = 0; + buffertype = 0; + holdbuffer = 0; + ReadJpeg( filename, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB); + text[0] = '\0'; } Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer ) { - if ( !initialised ) - Initialise(); - width = p_width; - height = p_height; - pixels = width*height; - colours = p_colours; - subpixelorder = p_subpixelorder; - size = pixels*colours; - buffer = 0; - holdbuffer = 0; - if ( p_buffer ) - { - allocation = size; - buffertype = ZM_BUFTYPE_DONTFREE; - buffer = p_buffer; - } - else - { - AllocImgBuffer(size); - } - text[0] = '\0'; + if ( !initialised ) + Initialise(); + width = p_width; + height = p_height; + pixels = width*height; + colours = p_colours; + subpixelorder = p_subpixelorder; + size = pixels*colours; + buffer = 0; + holdbuffer = 0; + if ( p_buffer ) + { + allocation = size; + buffertype = ZM_BUFTYPE_DONTFREE; + buffer = p_buffer; + } + else + { + AllocImgBuffer(size); + } + text[0] = '\0'; } Image::Image( const Image &p_image ) { - if ( !initialised ) - Initialise(); - width = p_image.width; - height = p_image.height; - pixels = p_image.pixels; - colours = p_image.colours; - subpixelorder = p_image.subpixelorder; - size = p_image.size; // allocation is set in AllocImgBuffer - buffer = 0; - holdbuffer = 0; - AllocImgBuffer(size); - (*fptr_imgbufcpy)(buffer, p_image.buffer, size); - strncpy( text, p_image.text, sizeof(text) ); + if ( !initialised ) + Initialise(); + width = p_image.width; + height = p_image.height; + pixels = p_image.pixels; + colours = p_image.colours; + subpixelorder = p_image.subpixelorder; + size = p_image.size; // allocation is set in AllocImgBuffer + buffer = 0; + holdbuffer = 0; + AllocImgBuffer(size); + (*fptr_imgbufcpy)(buffer, p_image.buffer, size); + strncpy( text, p_image.text, sizeof(text) ); } Image::~Image() { - DumpImgBuffer(); - if ( initialised ) - { - delete[] y_table; - delete[] uv_table; - delete[] r_v_table; - delete[] g_v_table; - delete[] g_u_table; - delete[] b_u_table; - initialised = false; - } - if ( jpg_dcinfo ) - { - jpeg_destroy_decompress( jpg_dcinfo ); - delete jpg_dcinfo; - jpg_dcinfo = 0; - } + DumpImgBuffer(); + if ( initialised ) + { + delete[] y_table; + delete[] uv_table; + delete[] r_v_table; + delete[] g_v_table; + delete[] g_u_table; + delete[] b_u_table; + initialised = false; + } + if ( jpg_dcinfo ) + { + jpeg_destroy_decompress( jpg_dcinfo ); + delete jpg_dcinfo; + jpg_dcinfo = 0; + } } void Image::Initialise() { - /* Assign the blend pointer to function */ - if(config.fast_image_blends) { - if(config.cpu_extensions && sseversion >= 20) { - fptr_blend = &sse2_fastblend; /* SSE2 fast blend */ - Debug(2,"Blend: Using SSE2 fast blend function"); - } else { - fptr_blend = &std_fastblend; /* standard fast blend */ - Debug(2,"Blend: Using fast blend function"); - } - } else { - fptr_blend = &std_blend; - Debug(2,"Blend: Using standard blend function"); - } - - __attribute__((aligned(16))) uint8_t blend1[16] = {142,255,159,91,88,227,0,52,37,80,152,97,104,252,90,82}; - __attribute__((aligned(16))) uint8_t blend2[16] = {129,56,136,96,119,149,94,29,96,176,1,144,230,203,111,172}; - __attribute__((aligned(16))) uint8_t blendres[16]; - __attribute__((aligned(16))) uint8_t blendexp[16] = {141,231,157,92,91,217,11,49,45,92,133,103,119,246,92,93}; /* Expected results for 12.5% blend */ - - (*fptr_blend)(blend1,blend2,blendres,16,12.5); - - /* Compare results with expected results */ - for(int i=0;i<16;i++) { - if(abs(blendexp[i] - blendres[i]) > 3) { - Panic("Blend function failed self-test: Results differ from the expected results"); - } - } - - fptr_delta8_rgb = &std_delta8_rgb; - fptr_delta8_bgr = &std_delta8_bgr; - - /* Assign the delta functions */ - if(config.cpu_extensions) { - if(sseversion >= 35) { - /* SSSE3 available */ - fptr_delta8_rgba = &ssse3_delta8_rgba; - fptr_delta8_bgra = &ssse3_delta8_bgra; - fptr_delta8_argb = &ssse3_delta8_argb; - fptr_delta8_abgr = &ssse3_delta8_abgr; - fptr_delta8_gray8 = &sse2_delta8_gray8; - Debug(2,"Delta: Using SSSE3 delta functions"); - } else if(sseversion >= 20) { - /* SSE2 available */ - fptr_delta8_rgba = &sse2_delta8_rgba; - fptr_delta8_bgra = &sse2_delta8_bgra; - fptr_delta8_argb = &sse2_delta8_argb; - fptr_delta8_abgr = &sse2_delta8_abgr; - /* - ** On some systems, the 4 SSE2 algorithms above might be a little slower than - ** the standard algorithms, especially on early Pentium 4 processors. - ** In that case, comment out the 4 lines above and uncomment the 4 lines below - */ - // fptr_delta8_rgba = &std_delta8_rgba; - // fptr_delta8_bgra = &std_delta8_bgra; - // fptr_delta8_argb = &std_delta8_argb; - // fptr_delta8_abgr = &std_delta8_abgr; - fptr_delta8_gray8 = &sse2_delta8_gray8; - Debug(2,"Delta: Using SSE2 delta functions"); - } else { - /* No suitable SSE version available */ - fptr_delta8_rgba = &std_delta8_rgba; - fptr_delta8_bgra = &std_delta8_bgra; - fptr_delta8_argb = &std_delta8_argb; - fptr_delta8_abgr = &std_delta8_abgr; - fptr_delta8_gray8 = &std_delta8_gray8; - Debug(2,"Delta: Using standard delta functions"); - } - } else { - /* CPU extensions disabled */ - fptr_delta8_rgba = &std_delta8_rgba; - fptr_delta8_bgra = &std_delta8_bgra; - fptr_delta8_argb = &std_delta8_argb; - fptr_delta8_abgr = &std_delta8_abgr; - fptr_delta8_gray8 = &std_delta8_gray8; - Debug(2,"Delta: CPU extensions disabled, using standard delta functions"); - } - - /* Use SSSE3 deinterlace functions? */ - if(config.cpu_extensions && sseversion >= 35) { - fptr_deinterlace_4field_rgba = &ssse3_deinterlace_4field_rgba; - fptr_deinterlace_4field_bgra = &ssse3_deinterlace_4field_bgra; - fptr_deinterlace_4field_argb = &ssse3_deinterlace_4field_argb; - fptr_deinterlace_4field_abgr = &ssse3_deinterlace_4field_abgr; - fptr_deinterlace_4field_gray8 = &ssse3_deinterlace_4field_gray8; - Debug(2,"Deinterlace: Using SSSE3 delta functions"); - } else { - fptr_deinterlace_4field_rgba = &std_deinterlace_4field_rgba; - fptr_deinterlace_4field_bgra = &std_deinterlace_4field_bgra; - fptr_deinterlace_4field_argb = &std_deinterlace_4field_argb; - fptr_deinterlace_4field_abgr = &std_deinterlace_4field_abgr; - fptr_deinterlace_4field_gray8 = &std_deinterlace_4field_gray8; - Debug(2,"Deinterlace: Using standard delta functions"); - } - - /* Use SSE2 aligned memory copy? */ - if(config.cpu_extensions && sseversion >= 20) { - fptr_imgbufcpy = &sse2_aligned_memcpy; - Debug(2,"Image buffer copy: Using SSE2 aligned memcpy"); - } else { - fptr_imgbufcpy = &memcpy; - Debug(2,"Image buffer copy: Using standard memcpy"); - } - - /* Code below relocated from zm_local_camera */ - Debug( 3, "Setting up static colour tables" ); - - y_table = new unsigned char[256]; - for ( int i = 0; i <= 255; i++ ) - { - unsigned char c = i; - if ( c <= 16 ) - y_table[c] = 0; - else if ( c >= 235 ) - y_table[c] = 255; - else - y_table[c] = (255*(c-16))/219; - } + /* Assign the blend pointer to function */ + if(config.fast_image_blends) { + if(config.cpu_extensions && sseversion >= 20) { + fptr_blend = &sse2_fastblend; /* SSE2 fast blend */ + Debug(2,"Blend: Using SSE2 fast blend function"); + } else { + fptr_blend = &std_fastblend; /* standard fast blend */ + Debug(2,"Blend: Using fast blend function"); + } + } else { + fptr_blend = &std_blend; + Debug(2,"Blend: Using standard blend function"); + } + + __attribute__((aligned(16))) uint8_t blend1[16] = {142,255,159,91,88,227,0,52,37,80,152,97,104,252,90,82}; + __attribute__((aligned(16))) uint8_t blend2[16] = {129,56,136,96,119,149,94,29,96,176,1,144,230,203,111,172}; + __attribute__((aligned(16))) uint8_t blendres[16]; + __attribute__((aligned(16))) uint8_t blendexp[16] = {141,231,157,92,91,217,11,49,45,92,133,103,119,246,92,93}; /* Expected results for 12.5% blend */ + + (*fptr_blend)(blend1,blend2,blendres,16,12.5); + + /* Compare results with expected results */ + for(int i=0;i<16;i++) { + if(abs(blendexp[i] - blendres[i]) > 3) { + Panic("Blend function failed self-test: Results differ from the expected results"); + } + } + + fptr_delta8_rgb = &std_delta8_rgb; + fptr_delta8_bgr = &std_delta8_bgr; + + /* Assign the delta functions */ + if(config.cpu_extensions) { + if(sseversion >= 35) { + /* SSSE3 available */ + fptr_delta8_rgba = &ssse3_delta8_rgba; + fptr_delta8_bgra = &ssse3_delta8_bgra; + fptr_delta8_argb = &ssse3_delta8_argb; + fptr_delta8_abgr = &ssse3_delta8_abgr; + fptr_delta8_gray8 = &sse2_delta8_gray8; + Debug(2,"Delta: Using SSSE3 delta functions"); + } else if(sseversion >= 20) { + /* SSE2 available */ + fptr_delta8_rgba = &sse2_delta8_rgba; + fptr_delta8_bgra = &sse2_delta8_bgra; + fptr_delta8_argb = &sse2_delta8_argb; + fptr_delta8_abgr = &sse2_delta8_abgr; + /* + ** On some systems, the 4 SSE2 algorithms above might be a little slower than + ** the standard algorithms, especially on early Pentium 4 processors. + ** In that case, comment out the 4 lines above and uncomment the 4 lines below + */ + // fptr_delta8_rgba = &std_delta8_rgba; + // fptr_delta8_bgra = &std_delta8_bgra; + // fptr_delta8_argb = &std_delta8_argb; + // fptr_delta8_abgr = &std_delta8_abgr; + fptr_delta8_gray8 = &sse2_delta8_gray8; + Debug(2,"Delta: Using SSE2 delta functions"); + } else { + /* No suitable SSE version available */ + fptr_delta8_rgba = &std_delta8_rgba; + fptr_delta8_bgra = &std_delta8_bgra; + fptr_delta8_argb = &std_delta8_argb; + fptr_delta8_abgr = &std_delta8_abgr; + fptr_delta8_gray8 = &std_delta8_gray8; + Debug(2,"Delta: Using standard delta functions"); + } + } else { + /* CPU extensions disabled */ + fptr_delta8_rgba = &std_delta8_rgba; + fptr_delta8_bgra = &std_delta8_bgra; + fptr_delta8_argb = &std_delta8_argb; + fptr_delta8_abgr = &std_delta8_abgr; + fptr_delta8_gray8 = &std_delta8_gray8; + Debug(2,"Delta: CPU extensions disabled, using standard delta functions"); + } + + /* Use SSSE3 deinterlace functions? */ + if(config.cpu_extensions && sseversion >= 35) { + fptr_deinterlace_4field_rgba = &ssse3_deinterlace_4field_rgba; + fptr_deinterlace_4field_bgra = &ssse3_deinterlace_4field_bgra; + fptr_deinterlace_4field_argb = &ssse3_deinterlace_4field_argb; + fptr_deinterlace_4field_abgr = &ssse3_deinterlace_4field_abgr; + fptr_deinterlace_4field_gray8 = &ssse3_deinterlace_4field_gray8; + Debug(2,"Deinterlace: Using SSSE3 delta functions"); + } else { + fptr_deinterlace_4field_rgba = &std_deinterlace_4field_rgba; + fptr_deinterlace_4field_bgra = &std_deinterlace_4field_bgra; + fptr_deinterlace_4field_argb = &std_deinterlace_4field_argb; + fptr_deinterlace_4field_abgr = &std_deinterlace_4field_abgr; + fptr_deinterlace_4field_gray8 = &std_deinterlace_4field_gray8; + Debug(2,"Deinterlace: Using standard delta functions"); + } + + /* Use SSE2 aligned memory copy? */ + if(config.cpu_extensions && sseversion >= 20) { + fptr_imgbufcpy = &sse2_aligned_memcpy; + Debug(2,"Image buffer copy: Using SSE2 aligned memcpy"); + } else { + fptr_imgbufcpy = &memcpy; + Debug(2,"Image buffer copy: Using standard memcpy"); + } + + /* Code below relocated from zm_local_camera */ + Debug( 3, "Setting up static colour tables" ); + + y_table = new unsigned char[256]; + for ( int i = 0; i <= 255; i++ ) + { + unsigned char c = i; + if ( c <= 16 ) + y_table[c] = 0; + else if ( c >= 235 ) + y_table[c] = 255; + else + y_table[c] = (255*(c-16))/219; + } - uv_table = new signed char[256]; - for ( int i = 0; i <= 255; i++ ) - { - unsigned char c = i; - if ( c <= 16 ) - uv_table[c] = -127; - else if ( c >= 240 ) - uv_table[c] = 127; - else - uv_table[c] = (127*(c-128))/112; - } + uv_table = new signed char[256]; + for ( int i = 0; i <= 255; i++ ) + { + unsigned char c = i; + if ( c <= 16 ) + uv_table[c] = -127; + else if ( c >= 240 ) + uv_table[c] = 127; + else + uv_table[c] = (127*(c-128))/112; + } - r_v_table = new short[255]; - g_v_table = new short[255]; - g_u_table = new short[255]; - b_u_table = new short[255]; - for ( int i = 0; i < 255; i++ ) - { - r_v_table[i] = (1402*(i-128))/1000; - g_u_table[i] = (344*(i-128))/1000; - g_v_table[i] = (714*(i-128))/1000; - b_u_table[i] = (1772*(i-128))/1000; - } - - initialised = true; + r_v_table = new short[255]; + g_v_table = new short[255]; + g_u_table = new short[255]; + b_u_table = new short[255]; + for ( int i = 0; i < 255; i++ ) + { + r_v_table[i] = (1402*(i-128))/1000; + g_u_table[i] = (344*(i-128))/1000; + g_v_table[i] = (714*(i-128))/1000; + b_u_table[i] = (1772*(i-128))/1000; + } + + initialised = true; } /* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) { - unsigned int newsize; + unsigned int newsize; - if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { - Error("WriteBuffer called with unexpected colours: %d",p_colours); - return NULL; - } - - if(!p_height || !p_width) { - Error("WriteBuffer called with invaid width or height: %d %d",p_width,p_height); - return NULL; - } - - if(p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) { - newsize = (p_width * p_height) * p_colours; - - if(buffer == NULL) { - AllocImgBuffer(newsize); - } else { - if(allocation < newsize) { - if(holdbuffer) { - Error("Held buffer is undersized for requested buffer"); - return NULL; - } else { - /* Replace buffer with a bigger one */ - //DumpImgBuffer(); // Done in AllocImgBuffer too - AllocImgBuffer(newsize); - } - } - } - - width = p_width; - height = p_height; - colours = p_colours; - subpixelorder = p_subpixelorder; - pixels = height*width; - size = newsize; - } - - return buffer; + if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { + Error("WriteBuffer called with unexpected colours: %d",p_colours); + return NULL; + } + + if(!p_height || !p_width) { + Error("WriteBuffer called with invaid width or height: %d %d",p_width,p_height); + return NULL; + } + + if(p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) { + newsize = (p_width * p_height) * p_colours; + + if(buffer == NULL) { + AllocImgBuffer(newsize); + } else { + if(allocation < newsize) { + if(holdbuffer) { + Error("Held buffer is undersized for requested buffer"); + return NULL; + } else { + /* Replace buffer with a bigger one */ + //DumpImgBuffer(); // Done in AllocImgBuffer too + AllocImgBuffer(newsize); + } + } + } + + width = p_width; + height = p_height; + colours = p_colours; + subpixelorder = p_subpixelorder; + pixels = height*width; + size = newsize; + } + + return buffer; } /* Assign an existing buffer to the image instead of copying from a source buffer. The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing. */ void Image::AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype) { - if(new_buffer == NULL) { - Error("Attempt to directly assign buffer from a NULL pointer"); - return; - } + if(new_buffer == NULL) { + Error("Attempt to directly assign buffer from a NULL pointer"); + return; + } - if(!p_height || !p_width) { - Error("Attempt to directly assign buffer with invalid width or height: %d %d",p_width,p_height); - return; - } + if(!p_height || !p_width) { + Error("Attempt to directly assign buffer with invalid width or height: %d %d",p_width,p_height); + return; + } - if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { - Error("Attempt to directly assign buffer with unexpected colours per pixel: %d",p_colours); - return; - } + if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { + Error("Attempt to directly assign buffer with unexpected colours per pixel: %d",p_colours); + return; + } - unsigned int new_buffer_size = ((p_width*p_height)*p_colours); - - if(buffer_size < new_buffer_size) { - Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",buffer_size, p_width, p_height, p_colours, new_buffer_size ); - return; - } - - if(holdbuffer && buffer) { - if(new_buffer_size > allocation) { - Error("Held buffer is undersized for assigned buffer"); - return; - } else { - width = p_width; - height = p_height; - colours = p_colours; - subpixelorder = p_subpixelorder; - pixels = height*width; - size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size - - /* Copy into the held buffer */ - if(new_buffer != buffer) - (*fptr_imgbufcpy)(buffer, new_buffer, size); - - /* Free the new buffer */ - DumpBuffer(new_buffer, p_buffertype); - } - } else { - /* Free an existing buffer if any */ - DumpImgBuffer(); - - width = p_width; - height = p_height; - colours = p_colours; - subpixelorder = p_subpixelorder; - pixels = height*width; - size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size - - allocation = buffer_size; - buffertype = p_buffertype; - buffer = new_buffer; - } - + unsigned int new_buffer_size = ((p_width*p_height)*p_colours); + + if(buffer_size < new_buffer_size) { + Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu",buffer_size, p_width, p_height, p_colours, new_buffer_size ); + return; + } + + if(holdbuffer && buffer) { + if(new_buffer_size > allocation) { + Error("Held buffer is undersized for assigned buffer"); + return; + } else { + width = p_width; + height = p_height; + colours = p_colours; + subpixelorder = p_subpixelorder; + pixels = height*width; + size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size + + /* Copy into the held buffer */ + if(new_buffer != buffer) + (*fptr_imgbufcpy)(buffer, new_buffer, size); + + /* Free the new buffer */ + DumpBuffer(new_buffer, p_buffertype); + } + } else { + /* Free an existing buffer if any */ + DumpImgBuffer(); + + width = p_width; + height = p_height; + colours = p_colours; + subpixelorder = p_subpixelorder; + pixels = height*width; + size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size + + allocation = buffer_size; + buffertype = p_buffertype; + buffer = new_buffer; + } + } void Image::Assign(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size) { - unsigned int new_size = (p_width * p_height) * p_colours; + unsigned int new_size = (p_width * p_height) * p_colours; - if(new_buffer == NULL) { - Error("Attempt to assign buffer from a NULL pointer"); - return; - } - - if(buffer_size < new_size) { - Error("Attempt to assign buffer from an undersized buffer of size: %zu",buffer_size); - return; - } - - if(!p_height || !p_width) { - Error("Attempt to assign buffer with invalid width or height: %d %d",p_width,p_height); - return; - } - - if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { - Error("Attempt to assign buffer with unexpected colours per pixel: %d",p_colours); - return; - } - - if ( !buffer || p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) { + if(new_buffer == NULL) { + Error("Attempt to assign buffer from a NULL pointer"); + return; + } + + if(buffer_size < new_size) { + Error("Attempt to assign buffer from an undersized buffer of size: %zu",buffer_size); + return; + } + + if(!p_height || !p_width) { + Error("Attempt to assign buffer with invalid width or height: %d %d",p_width,p_height); + return; + } + + if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { + Error("Attempt to assign buffer with unexpected colours per pixel: %d",p_colours); + return; + } + + if ( !buffer || p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) { - if (holdbuffer && buffer) { - if (new_size > allocation) { - Error("Held buffer is undersized for assigned buffer"); - return; - } - } else { - if(new_size > allocation || !buffer) { - DumpImgBuffer(); - AllocImgBuffer(new_size); - } - } - - width = p_width; - height = p_height; - pixels = width*height; - colours = p_colours; - subpixelorder = p_subpixelorder; - size = new_size; - } - - if(new_buffer != buffer) - (*fptr_imgbufcpy)(buffer, new_buffer, size); - + if (holdbuffer && buffer) { + if (new_size > allocation) { + Error("Held buffer is undersized for assigned buffer"); + return; + } + } else { + if(new_size > allocation || !buffer) { + DumpImgBuffer(); + AllocImgBuffer(new_size); + } + } + + width = p_width; + height = p_height; + pixels = width*height; + colours = p_colours; + subpixelorder = p_subpixelorder; + size = new_size; + } + + if(new_buffer != buffer) + (*fptr_imgbufcpy)(buffer, new_buffer, size); + } void Image::Assign( const Image &image ) { - unsigned int new_size = (image.width * image.height) * image.colours; - - if(image.buffer == NULL) { - Error("Attempt to assign image with an empty buffer"); - return; - } + unsigned int new_size = (image.width * image.height) * image.colours; - if(image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32) { - Error("Attempt to assign image with unexpected colours per pixel: %d",image.colours); - return; - } - - if ( !buffer || image.width != width || image.height != height || image.colours != colours || image.subpixelorder != subpixelorder) { + if(image.buffer == NULL) { + Error("Attempt to assign image with an empty buffer"); + return; + } + + if(image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32) { + Error("Attempt to assign image with unexpected colours per pixel: %d",image.colours); + return; + } + + if ( !buffer || image.width != width || image.height != height || image.colours != colours || image.subpixelorder != subpixelorder) { - if (holdbuffer && buffer) { - if (new_size > allocation) { - Error("Held buffer is undersized for assigned buffer"); - return; - } - } else { - if(new_size > allocation || !buffer) { - // DumpImgBuffer(); This is also done in AllocImgBuffer - AllocImgBuffer(new_size); - } - } - - width = image.width; - height = image.height; - pixels = width*height; - colours = image.colours; - subpixelorder = image.subpixelorder; - size = new_size; - } - - if(image.buffer != buffer) - (*fptr_imgbufcpy)(buffer, image.buffer, size); + if (holdbuffer && buffer) { + if (new_size > allocation) { + Error("Held buffer is undersized for assigned buffer"); + return; + } + } else { + if(new_size > allocation || !buffer) { + // DumpImgBuffer(); This is also done in AllocImgBuffer + AllocImgBuffer(new_size); + } + } + + width = image.width; + height = image.height; + pixels = width*height; + colours = image.colours; + subpixelorder = image.subpixelorder; + size = new_size; + } + + if(image.buffer != buffer) + (*fptr_imgbufcpy)(buffer, image.buffer, size); } Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits ) { - if ( colours != ZM_COLOUR_GRAY8 ) - { - Panic( "Attempt to highlight image edges when colours = %d", colours ); - } - - /* Convert the colour's RGBA subpixel order into the image's subpixel order */ - colour = rgb_convert(colour,p_subpixelorder); - - /* Create a new image of the target format */ - Image *high_image = new Image( width, height, p_colours, p_subpixelorder ); - uint8_t* high_buff = high_image->WriteBuffer(width, height, p_colours, p_subpixelorder); - - /* Set image to all black */ - high_image->Clear(); + if ( colours != ZM_COLOUR_GRAY8 ) + { + Panic( "Attempt to highlight image edges when colours = %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,p_subpixelorder); + + /* Create a new image of the target format */ + Image *high_image = new Image( width, height, p_colours, p_subpixelorder ); + uint8_t* high_buff = high_image->WriteBuffer(width, height, p_colours, p_subpixelorder); + + /* Set image to all black */ + high_image->Clear(); - unsigned int lo_x = limits?limits->Lo().X():0; - unsigned int lo_y = limits?limits->Lo().Y():0; - unsigned int hi_x = limits?limits->Hi().X():width-1; - unsigned int hi_y = limits?limits->Hi().Y():height-1; - - if ( p_colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - const uint8_t* p = buffer + (y * width) + lo_x; - uint8_t* phigh = high_buff + (y * width) + lo_x; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) - { - bool edge = false; - if ( *p ) - { - if ( !edge && x > 0 && !*(p-1) ) edge = true; - if ( !edge && x < (width-1) && !*(p+1) ) edge = true; - if ( !edge && y > 0 && !*(p-width) ) edge = true; - if ( !edge && y < (height-1) && !*(p+width) ) edge = true; - } - if ( edge ) - { - *phigh = colour; - } - } - } - } - else if ( p_colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - const uint8_t* p = buffer + (y * width) + lo_x; - uint8_t* phigh = high_buff + (((y * width) + lo_x) * 3); - for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) - { - bool edge = false; - if ( *p ) - { - if ( !edge && x > 0 && !*(p-1) ) edge = true; - if ( !edge && x < (width-1) && !*(p+1) ) edge = true; - if ( !edge && y > 0 && !*(p-width) ) edge = true; - if ( !edge && y < (height-1) && !*(p+width) ) edge = true; - } - if ( edge ) - { - RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour); - GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour); - BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour); - } - } - } - } - else if ( p_colours == ZM_COLOUR_RGB32 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - const uint8_t* p = buffer + (y * width) + lo_x; - Rgb* phigh = (Rgb*)(high_buff + (((y * width) + lo_x) * 4)); - for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) - { - bool edge = false; - if ( *p ) - { - if ( !edge && x > 0 && !*(p-1) ) edge = true; - if ( !edge && x < (width-1) && !*(p+1) ) edge = true; - if ( !edge && y > 0 && !*(p-width) ) edge = true; - if ( !edge && y < (height-1) && !*(p+width) ) edge = true; - } - if ( edge ) - { - *phigh = colour; - } - } - } - } - - return( high_image ); + unsigned int lo_x = limits?limits->Lo().X():0; + unsigned int lo_y = limits?limits->Lo().Y():0; + unsigned int hi_x = limits?limits->Hi().X():width-1; + unsigned int hi_y = limits?limits->Hi().Y():height-1; + + if ( p_colours == ZM_COLOUR_GRAY8 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + const uint8_t* p = buffer + (y * width) + lo_x; + uint8_t* phigh = high_buff + (y * width) + lo_x; + for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) + { + bool edge = false; + if ( *p ) + { + if ( !edge && x > 0 && !*(p-1) ) edge = true; + if ( !edge && x < (width-1) && !*(p+1) ) edge = true; + if ( !edge && y > 0 && !*(p-width) ) edge = true; + if ( !edge && y < (height-1) && !*(p+width) ) edge = true; + } + if ( edge ) + { + *phigh = colour; + } + } + } + } + else if ( p_colours == ZM_COLOUR_RGB24 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + const uint8_t* p = buffer + (y * width) + lo_x; + uint8_t* phigh = high_buff + (((y * width) + lo_x) * 3); + for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) + { + bool edge = false; + if ( *p ) + { + if ( !edge && x > 0 && !*(p-1) ) edge = true; + if ( !edge && x < (width-1) && !*(p+1) ) edge = true; + if ( !edge && y > 0 && !*(p-width) ) edge = true; + if ( !edge && y < (height-1) && !*(p+width) ) edge = true; + } + if ( edge ) + { + RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour); + } + } + } + } + else if ( p_colours == ZM_COLOUR_RGB32 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + const uint8_t* p = buffer + (y * width) + lo_x; + Rgb* phigh = (Rgb*)(high_buff + (((y * width) + lo_x) * 4)); + for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) + { + bool edge = false; + if ( *p ) + { + if ( !edge && x > 0 && !*(p-1) ) edge = true; + if ( !edge && x < (width-1) && !*(p+1) ) edge = true; + if ( !edge && y > 0 && !*(p-width) ) edge = true; + if ( !edge && y < (height-1) && !*(p+width) ) edge = true; + } + if ( edge ) + { + *phigh = colour; + } + } + } + } + + return( high_image ); } bool Image::ReadRaw( const char *filename ) { - FILE *infile; - if ( (infile = fopen( filename, "rb" )) == NULL ) - { - Error( "Can't open %s: %s", filename, strerror(errno) ); - return( false ); - } + FILE *infile; + if ( (infile = fopen( filename, "rb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } - struct stat statbuf; - if ( fstat( fileno(infile), &statbuf ) < 0 ) - { - Error( "Can't fstat %s: %s", filename, strerror(errno) ); - return( false ); - } + struct stat statbuf; + if ( fstat( fileno(infile), &statbuf ) < 0 ) + { + Error( "Can't fstat %s: %s", filename, strerror(errno) ); + return( false ); + } - if ( statbuf.st_size != size ) - { - Error( "Raw file size mismatch, expected %d bytes, found %ld", size, statbuf.st_size ); - return( false ); - } + if ( statbuf.st_size != size ) + { + Error( "Raw file size mismatch, expected %d bytes, found %ld", size, statbuf.st_size ); + return( false ); + } - if ( fread( buffer, size, 1, infile ) < 1 ) - { - Fatal( "Unable to read from '%s': %s", filename, strerror(errno) ); - return( false ); - } + if ( fread( buffer, size, 1, infile ) < 1 ) + { + Fatal( "Unable to read from '%s': %s", filename, strerror(errno) ); + return( false ); + } - fclose( infile ); + fclose( infile ); - return( true ); + return( true ); } bool Image::WriteRaw( const char *filename ) const { - FILE *outfile; - if ( (outfile = fopen( filename, "wb" )) == NULL ) - { - Error( "Can't open %s: %s", filename, strerror(errno) ); - return( false ); - } + FILE *outfile; + if ( (outfile = fopen( filename, "wb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } - if ( fwrite( buffer, size, 1, outfile ) != 1 ) - { - Error( "Unable to write to '%s': %s", filename, strerror(errno) ); - return( false ); - } + if ( fwrite( buffer, size, 1, outfile ) != 1 ) + { + Error( "Unable to write to '%s': %s", filename, strerror(errno) ); + return( false ); + } - fclose( outfile ); + fclose( outfile ); - return( true ); + return( true ); } bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int p_subpixelorder) { - unsigned int new_width, new_height, new_colours, new_subpixelorder; - struct jpeg_decompress_struct *cinfo = jpg_dcinfo; + unsigned int new_width, new_height, new_colours, new_subpixelorder; + struct jpeg_decompress_struct *cinfo = jpg_dcinfo; - if ( !cinfo ) - { - cinfo = jpg_dcinfo = new jpeg_decompress_struct; - cinfo->err = jpeg_std_error( &jpg_err.pub ); - jpg_err.pub.error_exit = zm_jpeg_error_exit; - jpg_err.pub.emit_message = zm_jpeg_emit_message; - jpeg_create_decompress( cinfo ); - } + if ( !cinfo ) + { + cinfo = jpg_dcinfo = new jpeg_decompress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_decompress( cinfo ); + } - FILE *infile; - if ( (infile = fopen( filename, "rb" )) == NULL ) - { - Error( "Can't open %s: %s", filename, strerror(errno) ); - return( false ); - } + FILE *infile; + if ( (infile = fopen( filename, "rb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } - if ( setjmp( jpg_err.setjmp_buffer ) ) - { - jpeg_abort_decompress( cinfo ); - fclose( infile ); - return( false ); - } + if ( setjmp( jpg_err.setjmp_buffer ) ) + { + jpeg_abort_decompress( cinfo ); + fclose( infile ); + return( false ); + } - jpeg_stdio_src( cinfo, infile ); + jpeg_stdio_src( cinfo, infile ); - jpeg_read_header( cinfo, TRUE ); + jpeg_read_header( cinfo, TRUE ); - if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) - { - Error( "Unexpected colours when reading jpeg image: %d", colours ); - jpeg_abort_decompress( cinfo ); - fclose( infile ); - return( false ); - } - - /* Check if the image has at least one huffman table defined. If not, use the standard ones */ - /* This is required for the MJPEG capture palette of USB devices */ - if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { - zm_use_std_huff_tables(cinfo); - } + if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) + { + Error( "Unexpected colours when reading jpeg image: %d", colours ); + jpeg_abort_decompress( cinfo ); + fclose( infile ); + return( false ); + } + + /* Check if the image has at least one huffman table defined. If not, use the standard ones */ + /* This is required for the MJPEG capture palette of USB devices */ + if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { + zm_use_std_huff_tables(cinfo); + } - new_width = cinfo->image_width; - new_height = cinfo->image_height; + new_width = cinfo->image_width; + new_height = cinfo->image_height; - if ( width != new_width || height != new_height ) - { - Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height); - } - - switch(p_colours) { - case ZM_COLOUR_GRAY8: - { - cinfo->out_color_space = JCS_GRAYSCALE; - new_colours = ZM_COLOUR_GRAY8; - new_subpixelorder = ZM_SUBPIX_ORDER_NONE; - break; - } - case ZM_COLOUR_RGB32: - { + if ( width != new_width || height != new_height ) + { + Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height); + } + + switch(p_colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->out_color_space = JCS_GRAYSCALE; + new_colours = ZM_COLOUR_GRAY8; + new_subpixelorder = ZM_SUBPIX_ORDER_NONE; + break; + } + case ZM_COLOUR_RGB32: + { #ifdef JCS_EXTENSIONS - new_colours = ZM_COLOUR_RGB32; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - cinfo->out_color_space = JCS_EXT_BGRX; - new_subpixelorder = ZM_SUBPIX_ORDER_BGRA; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - cinfo->out_color_space = JCS_EXT_XRGB; - new_subpixelorder = ZM_SUBPIX_ORDER_ARGB; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - cinfo->out_color_space = JCS_EXT_XBGR; - new_subpixelorder = ZM_SUBPIX_ORDER_ABGR; - } else { - /* Assume RGBA */ - cinfo->out_color_space = JCS_EXT_RGBX; - new_subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } - break; + new_colours = ZM_COLOUR_RGB32; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->out_color_space = JCS_EXT_BGRX; + new_subpixelorder = ZM_SUBPIX_ORDER_BGRA; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->out_color_space = JCS_EXT_XRGB; + new_subpixelorder = ZM_SUBPIX_ORDER_ARGB; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->out_color_space = JCS_EXT_XBGR; + new_subpixelorder = ZM_SUBPIX_ORDER_ABGR; + } else { + /* Assume RGBA */ + cinfo->out_color_space = JCS_EXT_RGBX; + new_subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } + break; #else - Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); + Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); #endif - } - case ZM_COLOUR_RGB24: - default: - { - new_colours = ZM_COLOUR_RGB24; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { -#ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_BGR; - new_subpixelorder = ZM_SUBPIX_ORDER_BGR; + } + case ZM_COLOUR_RGB24: + default: + { + new_colours = ZM_COLOUR_RGB24; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_BGR; + new_subpixelorder = ZM_SUBPIX_ORDER_BGR; #else - Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); - cinfo->out_color_space = JCS_RGB; - new_subpixelorder = ZM_SUBPIX_ORDER_RGB; + Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); + cinfo->out_color_space = JCS_RGB; + new_subpixelorder = ZM_SUBPIX_ORDER_RGB; #endif - } else { - /* Assume RGB */ + } else { + /* Assume RGB */ /* #ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_RGB; + cinfo->out_color_space = JCS_EXT_RGB; #else - cinfo->out_color_space = JCS_RGB; + cinfo->out_color_space = JCS_RGB; #endif */ - cinfo->out_color_space = JCS_RGB; - new_subpixelorder = ZM_SUBPIX_ORDER_RGB; - } - break; - } - } - - if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { - Error("Failed requesting writeable buffer for reading JPEG image."); - jpeg_abort_decompress( cinfo ); - fclose( infile ); - return( false ); - } + cinfo->out_color_space = JCS_RGB; + new_subpixelorder = ZM_SUBPIX_ORDER_RGB; + } + break; + } + } + + if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { + Error("Failed requesting writeable buffer for reading JPEG image."); + jpeg_abort_decompress( cinfo ); + fclose( infile ); + return( false ); + } - jpeg_start_decompress( cinfo ); + jpeg_start_decompress( cinfo ); - JSAMPROW row_pointer; /* pointer to a single row */ - int row_stride = width * colours; /* physical row width in buffer */ - while ( cinfo->output_scanline < cinfo->output_height ) - { - row_pointer = &buffer[cinfo->output_scanline * row_stride]; - jpeg_read_scanlines( cinfo, &row_pointer, 1 ); - } + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = width * colours; /* physical row width in buffer */ + while ( cinfo->output_scanline < cinfo->output_height ) + { + row_pointer = &buffer[cinfo->output_scanline * row_stride]; + jpeg_read_scanlines( cinfo, &row_pointer, 1 ); + } - jpeg_finish_decompress( cinfo ); + jpeg_finish_decompress( cinfo ); - fclose( infile ); + fclose( infile ); - return( true ); + return( true ); } // Multiple calling formats to permit inclusion (or not) of both quality_override and timestamp (exif), with suitable defaults. @@ -793,2326 +793,2326 @@ bool Image::ReadJpeg( const char *filename, unsigned int p_colours, unsigned int bool Image::WriteJpeg( const char *filename, int quality_override) const { - return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); + return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); } bool Image::WriteJpeg( const char *filename) const { - return Image::WriteJpeg(filename, 0, (timeval){0,0}); + return Image::WriteJpeg(filename, 0, (timeval){0,0}); } bool Image::WriteJpeg( const char *filename, struct timeval timestamp ) const { - return Image::WriteJpeg(filename,0,timestamp); + return Image::WriteJpeg(filename,0,timestamp); } bool Image::WriteJpeg( const char *filename, int quality_override, struct timeval timestamp ) const { - if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) - { - Image temp_image( *this ); - temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); - return( temp_image.WriteJpeg( filename, quality_override, timestamp) ); - } - int quality = quality_override?quality_override:config.jpeg_file_quality; + if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) + { + Image temp_image( *this ); + temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + return( temp_image.WriteJpeg( filename, quality_override, timestamp) ); + } + int quality = quality_override?quality_override:config.jpeg_file_quality; - struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; + struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; - if ( !cinfo ) - { - cinfo = jpg_ccinfo[quality] = new jpeg_compress_struct; - cinfo->err = jpeg_std_error( &jpg_err.pub ); - jpg_err.pub.error_exit = zm_jpeg_error_exit; - jpg_err.pub.emit_message = zm_jpeg_emit_message; - jpeg_create_compress( cinfo ); - } + if ( !cinfo ) + { + cinfo = jpg_ccinfo[quality] = new jpeg_compress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_compress( cinfo ); + } - FILE *outfile; - if ( (outfile = fopen( filename, "wb" )) == NULL ) - { - Error( "Can't open %s: %s", filename, strerror(errno) ); - return( false ); - } - jpeg_stdio_dest( cinfo, outfile ); + FILE *outfile; + if ( (outfile = fopen( filename, "wb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } + jpeg_stdio_dest( cinfo, outfile ); - cinfo->image_width = width; /* image width and height, in pixels */ - cinfo->image_height = height; - - switch(colours) { - case ZM_COLOUR_GRAY8: - { - cinfo->input_components = 1; - cinfo->in_color_space = JCS_GRAYSCALE; - break; - } - case ZM_COLOUR_RGB32: - { + cinfo->image_width = width; /* image width and height, in pixels */ + cinfo->image_height = height; + + switch(colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + break; + } + case ZM_COLOUR_RGB32: + { #ifdef JCS_EXTENSIONS - cinfo->input_components = 4; - if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - cinfo->in_color_space = JCS_EXT_BGRX; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - cinfo->in_color_space = JCS_EXT_XRGB; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - cinfo->in_color_space = JCS_EXT_XBGR; - } else { - /* Assume RGBA */ - cinfo->in_color_space = JCS_EXT_RGBX; - } + cinfo->input_components = 4; + if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->in_color_space = JCS_EXT_BGRX; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->in_color_space = JCS_EXT_XRGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->in_color_space = JCS_EXT_XBGR; + } else { + /* Assume RGBA */ + cinfo->in_color_space = JCS_EXT_RGBX; + } #else - Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); - jpeg_abort_compress( cinfo ); - fclose(outfile); - return(false); + Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); + jpeg_abort_compress( cinfo ); + fclose(outfile); + return(false); #endif - break; - } - case ZM_COLOUR_RGB24: - default: - { - cinfo->input_components = 3; - if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + break; + } + case ZM_COLOUR_RGB24: + default: + { + cinfo->input_components = 3; + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { #ifdef JCS_EXTENSIONS - cinfo->in_color_space = JCS_EXT_BGR; + cinfo->in_color_space = JCS_EXT_BGR; #else - Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); - jpeg_abort_compress( cinfo ); - fclose(outfile); - return(false); + Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); + jpeg_abort_compress( cinfo ); + fclose(outfile); + return(false); #endif - } else { - /* Assume RGB */ + } else { + /* Assume RGB */ /* #ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_RGB; + cinfo->out_color_space = JCS_EXT_RGB; #else - cinfo->out_color_space = JCS_RGB; + cinfo->out_color_space = JCS_RGB; #endif */ - cinfo->in_color_space = JCS_RGB; - } - break; - } - } - - jpeg_set_defaults( cinfo ); - jpeg_set_quality( cinfo, quality, FALSE ); - cinfo->dct_method = JDCT_FASTEST; + cinfo->in_color_space = JCS_RGB; + } + break; + } + } + + jpeg_set_defaults( cinfo ); + jpeg_set_quality( cinfo, quality, FALSE ); + cinfo->dct_method = JDCT_FASTEST; - jpeg_start_compress( cinfo, TRUE ); - if ( config.add_jpeg_comments && text[0] ) - { - jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); - } - // If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal - // No timestamp just leave off the exif section. - if(timestamp.tv_sec) - { - #define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds - #define EXIFTIMES_MS_LEN 0x03 - #define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes - #define EXIFTIMES_LEN 0x13 // = 19 - #define EXIF_CODE 0xE1 + jpeg_start_compress( cinfo, TRUE ); + if ( config.add_jpeg_comments && text[0] ) + { + jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); + } + // If we have a non-zero time (meaning a parameter was passed in), then form a simple exif segment with that time as DateTimeOriginal and SubsecTimeOriginal + // No timestamp just leave off the exif section. + if(timestamp.tv_sec) + { + #define EXIFTIMES_MS_OFFSET 0x36 // three decimal digits for milliseconds + #define EXIFTIMES_MS_LEN 0x03 + #define EXIFTIMES_OFFSET 0x3E // 19 characters format '2015:07:21 13:14:45' not including quotes + #define EXIFTIMES_LEN 0x13 // = 19 + #define EXIF_CODE 0xE1 - char timebuf[64], msbuf[64]; - strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec))); - snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it - unsigned char exiftimes[82] = { - 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x03, 0x90, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x91, 0x92, - 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00 }; - memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); - memcpy(&exiftimes[EXIFTIMES_MS_OFFSET], msbuf ,EXIFTIMES_MS_LEN); - jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); - } + char timebuf[64], msbuf[64]; + strftime(timebuf, sizeof timebuf, "%Y:%m:%d %H:%M:%S", localtime(&(timestamp.tv_sec))); + snprintf(msbuf, sizeof msbuf, "%06d",(int)(timestamp.tv_usec)); // we only use milliseconds because that's all defined in exif, but this is the whole microseconds because we have it + unsigned char exiftimes[82] = { + 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x03, 0x90, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x91, 0x92, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00 }; + memcpy(&exiftimes[EXIFTIMES_OFFSET], timebuf,EXIFTIMES_LEN); + memcpy(&exiftimes[EXIFTIMES_MS_OFFSET], msbuf ,EXIFTIMES_MS_LEN); + jpeg_write_marker (cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes) ); + } - JSAMPROW row_pointer; /* pointer to a single row */ - int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ - while ( cinfo->next_scanline < cinfo->image_height ) - { - row_pointer = &buffer[cinfo->next_scanline * row_stride]; - jpeg_write_scanlines( cinfo, &row_pointer, 1 ); - } + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ + while ( cinfo->next_scanline < cinfo->image_height ) + { + row_pointer = &buffer[cinfo->next_scanline * row_stride]; + jpeg_write_scanlines( cinfo, &row_pointer, 1 ); + } - jpeg_finish_compress( cinfo ); + jpeg_finish_compress( cinfo ); - fclose( outfile ); + fclose( outfile ); - return( true ); + return( true ); } bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, unsigned int p_colours, unsigned int p_subpixelorder) { - unsigned int new_width, new_height, new_colours, new_subpixelorder; - struct jpeg_decompress_struct *cinfo = jpg_dcinfo; + unsigned int new_width, new_height, new_colours, new_subpixelorder; + struct jpeg_decompress_struct *cinfo = jpg_dcinfo; - if ( !cinfo ) - { - cinfo = jpg_dcinfo = new jpeg_decompress_struct; - cinfo->err = jpeg_std_error( &jpg_err.pub ); - jpg_err.pub.error_exit = zm_jpeg_error_exit; - jpg_err.pub.emit_message = zm_jpeg_emit_message; - jpeg_create_decompress( cinfo ); - } + if ( !cinfo ) + { + cinfo = jpg_dcinfo = new jpeg_decompress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_decompress( cinfo ); + } - if ( setjmp( jpg_err.setjmp_buffer ) ) - { - jpeg_abort_decompress( cinfo ); - return( false ); - } + if ( setjmp( jpg_err.setjmp_buffer ) ) + { + jpeg_abort_decompress( cinfo ); + return( false ); + } - zm_jpeg_mem_src( cinfo, inbuffer, inbuffer_size ); + zm_jpeg_mem_src( cinfo, inbuffer, inbuffer_size ); - jpeg_read_header( cinfo, TRUE ); + jpeg_read_header( cinfo, TRUE ); - if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) - { - Error( "Unexpected colours when reading jpeg image: %d", colours ); - jpeg_abort_decompress( cinfo ); - return( false ); - } - - /* Check if the image has at least one huffman table defined. If not, use the standard ones */ - /* This is required for the MJPEG capture palette of USB devices */ - if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { - zm_use_std_huff_tables(cinfo); - } + if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) + { + Error( "Unexpected colours when reading jpeg image: %d", colours ); + jpeg_abort_decompress( cinfo ); + return( false ); + } + + /* Check if the image has at least one huffman table defined. If not, use the standard ones */ + /* This is required for the MJPEG capture palette of USB devices */ + if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { + zm_use_std_huff_tables(cinfo); + } - new_width = cinfo->image_width; - new_height = cinfo->image_height; + new_width = cinfo->image_width; + new_height = cinfo->image_height; - if ( width != new_width || height != new_height ) - { - Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height); - } - - switch(p_colours) { - case ZM_COLOUR_GRAY8: - { - cinfo->out_color_space = JCS_GRAYSCALE; - new_colours = ZM_COLOUR_GRAY8; - new_subpixelorder = ZM_SUBPIX_ORDER_NONE; - break; - } - case ZM_COLOUR_RGB32: - { + if ( width != new_width || height != new_height ) + { + Debug(9,"Image dimensions differ. Old: %ux%u New: %ux%u",width,height,new_width,new_height); + } + + switch(p_colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->out_color_space = JCS_GRAYSCALE; + new_colours = ZM_COLOUR_GRAY8; + new_subpixelorder = ZM_SUBPIX_ORDER_NONE; + break; + } + case ZM_COLOUR_RGB32: + { #ifdef JCS_EXTENSIONS - new_colours = ZM_COLOUR_RGB32; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - cinfo->out_color_space = JCS_EXT_BGRX; - new_subpixelorder = ZM_SUBPIX_ORDER_BGRA; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - cinfo->out_color_space = JCS_EXT_XRGB; - new_subpixelorder = ZM_SUBPIX_ORDER_ARGB; - } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - cinfo->out_color_space = JCS_EXT_XBGR; - new_subpixelorder = ZM_SUBPIX_ORDER_ABGR; - } else { - /* Assume RGBA */ - cinfo->out_color_space = JCS_EXT_RGBX; - new_subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } - break; + new_colours = ZM_COLOUR_RGB32; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->out_color_space = JCS_EXT_BGRX; + new_subpixelorder = ZM_SUBPIX_ORDER_BGRA; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->out_color_space = JCS_EXT_XRGB; + new_subpixelorder = ZM_SUBPIX_ORDER_ARGB; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->out_color_space = JCS_EXT_XBGR; + new_subpixelorder = ZM_SUBPIX_ORDER_ABGR; + } else { + /* Assume RGBA */ + cinfo->out_color_space = JCS_EXT_RGBX; + new_subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } + break; #else - Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); + Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); #endif - } - case ZM_COLOUR_RGB24: - default: - { - new_colours = ZM_COLOUR_RGB24; - if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { -#ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_BGR; - new_subpixelorder = ZM_SUBPIX_ORDER_BGR; + } + case ZM_COLOUR_RGB24: + default: + { + new_colours = ZM_COLOUR_RGB24; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_BGR; + new_subpixelorder = ZM_SUBPIX_ORDER_BGR; #else - Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); - cinfo->out_color_space = JCS_RGB; - new_subpixelorder = ZM_SUBPIX_ORDER_RGB; + Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); + cinfo->out_color_space = JCS_RGB; + new_subpixelorder = ZM_SUBPIX_ORDER_RGB; #endif - } else { - /* Assume RGB */ + } else { + /* Assume RGB */ /* #ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_RGB; + cinfo->out_color_space = JCS_EXT_RGB; #else - cinfo->out_color_space = JCS_RGB; + cinfo->out_color_space = JCS_RGB; #endif */ - cinfo->out_color_space = JCS_RGB; - new_subpixelorder = ZM_SUBPIX_ORDER_RGB; - } - break; - } - } - - if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { - Error("Failed requesting writeable buffer for reading JPEG image."); - jpeg_abort_decompress( cinfo ); - return( false ); - } + cinfo->out_color_space = JCS_RGB; + new_subpixelorder = ZM_SUBPIX_ORDER_RGB; + } + break; + } + } + + if(WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL) { + Error("Failed requesting writeable buffer for reading JPEG image."); + jpeg_abort_decompress( cinfo ); + return( false ); + } - jpeg_start_decompress( cinfo ); + jpeg_start_decompress( cinfo ); - JSAMPROW row_pointer; /* pointer to a single row */ - int row_stride = width * colours; /* physical row width in buffer */ - while ( cinfo->output_scanline < cinfo->output_height ) - { - row_pointer = &buffer[cinfo->output_scanline * row_stride]; - jpeg_read_scanlines( cinfo, &row_pointer, 1 ); - } + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = width * colours; /* physical row width in buffer */ + while ( cinfo->output_scanline < cinfo->output_height ) + { + row_pointer = &buffer[cinfo->output_scanline * row_stride]; + jpeg_read_scanlines( cinfo, &row_pointer, 1 ); + } - jpeg_finish_decompress( cinfo ); + jpeg_finish_decompress( cinfo ); - return( true ); + return( true ); } bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override ) const { - if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) - { - Image temp_image( *this ); - temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); - return( temp_image.EncodeJpeg( outbuffer, outbuffer_size, quality_override ) ); - } + if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) + { + Image temp_image( *this ); + temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + return( temp_image.EncodeJpeg( outbuffer, outbuffer_size, quality_override ) ); + } - int quality = quality_override?quality_override:config.jpeg_stream_quality; + int quality = quality_override?quality_override:config.jpeg_stream_quality; - struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; + struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; - if ( !cinfo ) - { - cinfo = jpg_ccinfo[quality] = new jpeg_compress_struct; - cinfo->err = jpeg_std_error( &jpg_err.pub ); - jpg_err.pub.error_exit = zm_jpeg_error_exit; - jpg_err.pub.emit_message = zm_jpeg_emit_message; - jpeg_create_compress( cinfo ); - } + if ( !cinfo ) + { + cinfo = jpg_ccinfo[quality] = new jpeg_compress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_compress( cinfo ); + } - zm_jpeg_mem_dest( cinfo, outbuffer, outbuffer_size ); + zm_jpeg_mem_dest( cinfo, outbuffer, outbuffer_size ); - cinfo->image_width = width; /* image width and height, in pixels */ - cinfo->image_height = height; + cinfo->image_width = width; /* image width and height, in pixels */ + cinfo->image_height = height; - switch(colours) { - case ZM_COLOUR_GRAY8: - { - cinfo->input_components = 1; - cinfo->in_color_space = JCS_GRAYSCALE; - break; - } - case ZM_COLOUR_RGB32: - { + switch(colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + break; + } + case ZM_COLOUR_RGB32: + { #ifdef JCS_EXTENSIONS - cinfo->input_components = 4; - if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - cinfo->in_color_space = JCS_EXT_BGRX; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - cinfo->in_color_space = JCS_EXT_XRGB; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - cinfo->in_color_space = JCS_EXT_XBGR; - } else { - /* Assume RGBA */ - cinfo->in_color_space = JCS_EXT_RGBX; - } + cinfo->input_components = 4; + if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->in_color_space = JCS_EXT_BGRX; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->in_color_space = JCS_EXT_XRGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->in_color_space = JCS_EXT_XBGR; + } else { + /* Assume RGBA */ + cinfo->in_color_space = JCS_EXT_RGBX; + } #else - Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); - jpeg_abort_compress( cinfo ); - return(false); + Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); + jpeg_abort_compress( cinfo ); + return(false); #endif - break; - } - case ZM_COLOUR_RGB24: - default: - { - cinfo->input_components = 3; - if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + break; + } + case ZM_COLOUR_RGB24: + default: + { + cinfo->input_components = 3; + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { #ifdef JCS_EXTENSIONS - cinfo->in_color_space = JCS_EXT_BGR; + cinfo->in_color_space = JCS_EXT_BGR; #else - Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); - jpeg_abort_compress( cinfo ); - return(false); + Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); + jpeg_abort_compress( cinfo ); + return(false); #endif - } else { - /* Assume RGB */ + } else { + /* Assume RGB */ /* #ifdef JCS_EXTENSIONS - cinfo->out_color_space = JCS_EXT_RGB; + cinfo->out_color_space = JCS_EXT_RGB; #else - cinfo->out_color_space = JCS_RGB; + cinfo->out_color_space = JCS_RGB; #endif */ - cinfo->in_color_space = JCS_RGB; - } - break; - } - } - - jpeg_set_defaults( cinfo ); - jpeg_set_quality( cinfo, quality, FALSE ); - cinfo->dct_method = JDCT_FASTEST; + cinfo->in_color_space = JCS_RGB; + } + break; + } + } + + jpeg_set_defaults( cinfo ); + jpeg_set_quality( cinfo, quality, FALSE ); + cinfo->dct_method = JDCT_FASTEST; - jpeg_start_compress( cinfo, TRUE ); + jpeg_start_compress( cinfo, TRUE ); - JSAMPROW row_pointer; /* pointer to a single row */ - int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ - while ( cinfo->next_scanline < cinfo->image_height ) - { - row_pointer = &buffer[cinfo->next_scanline * row_stride]; - jpeg_write_scanlines( cinfo, &row_pointer, 1 ); - } + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ + while ( cinfo->next_scanline < cinfo->image_height ) + { + row_pointer = &buffer[cinfo->next_scanline * row_stride]; + jpeg_write_scanlines( cinfo, &row_pointer, 1 ); + } - jpeg_finish_compress( cinfo ); + jpeg_finish_compress( cinfo ); - return( true ); + return( true ); } #if HAVE_ZLIB_H bool Image::Unzip( const Bytef *inbuffer, unsigned long inbuffer_size ) { - unsigned long zip_size = size; - int result = uncompress( buffer, &zip_size, inbuffer, inbuffer_size ); - if ( result != Z_OK ) - { - Error( "Unzip failed, result = %d", result ); - return( false ); - } - if ( zip_size != (unsigned int)size ) - { - Error( "Unzip failed, size mismatch, expected %d bytes, got %ld", size, zip_size ); - return( false ); - } - return( true ); + unsigned long zip_size = size; + int result = uncompress( buffer, &zip_size, inbuffer, inbuffer_size ); + if ( result != Z_OK ) + { + Error( "Unzip failed, result = %d", result ); + return( false ); + } + if ( zip_size != (unsigned int)size ) + { + Error( "Unzip failed, size mismatch, expected %d bytes, got %ld", size, zip_size ); + return( false ); + } + return( true ); } bool Image::Zip( Bytef *outbuffer, unsigned long *outbuffer_size, int compression_level ) const { - int result = compress2( outbuffer, outbuffer_size, buffer, size, compression_level ); - if ( result != Z_OK ) - { - Error( "Zip failed, result = %d", result ); - return( false ); - } - return( true ); + int result = compress2( outbuffer, outbuffer_size, buffer, size, compression_level ); + if ( result != Z_OK ) + { + Error( "Zip failed, result = %d", result ); + return( false ); + } + return( true ); } #endif // HAVE_ZLIB_H bool Image::Crop( unsigned int lo_x, unsigned int lo_y, unsigned int hi_x, unsigned int hi_y ) { - unsigned int new_width = (hi_x-lo_x)+1; - unsigned int new_height = (hi_y-lo_y)+1; + unsigned int new_width = (hi_x-lo_x)+1; + unsigned int new_height = (hi_y-lo_y)+1; - if ( lo_x > hi_x || lo_y > hi_y ) - { - Error( "Invalid or reversed crop region %d,%d -> %d,%d", lo_x, lo_y, hi_x, hi_y ); - return( false ); - } - if ( lo_x < 0 || hi_x > (width-1) || ( lo_y < 0 || hi_y > (height-1) ) ) - { - Error( "Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d", lo_x, lo_y, hi_x, hi_y, width-1, height-1 ); - return( false ); - } + if ( lo_x > hi_x || lo_y > hi_y ) + { + Error( "Invalid or reversed crop region %d,%d -> %d,%d", lo_x, lo_y, hi_x, hi_y ); + return( false ); + } + if ( lo_x < 0 || hi_x > (width-1) || ( lo_y < 0 || hi_y > (height-1) ) ) + { + Error( "Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d", lo_x, lo_y, hi_x, hi_y, width-1, height-1 ); + return( false ); + } - if ( new_width == width && new_height == height ) - { - return( true ); - } + if ( new_width == width && new_height == height ) + { + return( true ); + } - unsigned int new_size = new_width*new_height*colours; - uint8_t *new_buffer = AllocBuffer(new_size); - - unsigned int new_stride = new_width*colours; - for ( unsigned int y = lo_y, ny = 0; y <= hi_y; y++, ny++ ) - { - unsigned char *pbuf = &buffer[((y*width)+lo_x)*colours]; - unsigned char *pnbuf = &new_buffer[(ny*new_width)*colours]; - memcpy( pnbuf, pbuf, new_stride ); - } + unsigned int new_size = new_width*new_height*colours; + uint8_t *new_buffer = AllocBuffer(new_size); + + unsigned int new_stride = new_width*colours; + for ( unsigned int y = lo_y, ny = 0; y <= hi_y; y++, ny++ ) + { + unsigned char *pbuf = &buffer[((y*width)+lo_x)*colours]; + unsigned char *pnbuf = &new_buffer[(ny*new_width)*colours]; + memcpy( pnbuf, pbuf, new_stride ); + } - AssignDirect(new_width, new_height, colours, subpixelorder, new_buffer, new_size, ZM_BUFTYPE_ZM); + AssignDirect(new_width, new_height, colours, subpixelorder, new_buffer, new_size, ZM_BUFTYPE_ZM); - return( true ); + return( true ); } bool Image::Crop( const Box &limits ) { - return( Crop( limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() ) ); + return( Crop( limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() ) ); } /* Far from complete */ /* Need to implement all possible of overlays possible */ void Image::Overlay( const Image &image ) { - if ( !(width == image.width && height == image.height) ) - { - Panic( "Attempt to overlay different sized images, expected %dx%d, got %dx%d", width, height, image.width, image.height ); - } - - if( colours == image.colours && subpixelorder != image.subpixelorder ) { - Warning("Attempt to overlay images of same format but with different subpixel order."); - } - - /* Grayscale ontop of grayscale - complete */ - if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_GRAY8 ) { - const uint8_t* const max_ptr = buffer+size; - const uint8_t* psrc = image.buffer; - uint8_t* pdest = buffer; - - while( pdest < max_ptr ) - { - if ( *psrc ) - { - *pdest = *psrc; - } - pdest++; - psrc++; - } - - /* RGB24 ontop of grayscale - convert to same format first - complete */ - } else if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB24 ) { - Colourise(image.colours, image.subpixelorder); - - const uint8_t* const max_ptr = buffer+size; - const uint8_t* psrc = image.buffer; - uint8_t* pdest = buffer; - - while( pdest < max_ptr ) - { - if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) - { - RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); - GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); - BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); - } - pdest += 3; - psrc += 3; - } - - /* RGB32 ontop of grayscale - convert to same format first - complete */ - } else if( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB32 ) { - Colourise(image.colours, image.subpixelorder); - - const Rgb* const max_ptr = (Rgb*)(buffer+size); - const Rgb* prsrc = (Rgb*)image.buffer; - Rgb* prdest = (Rgb*)buffer; - - if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ - while (prdest < max_ptr) { - if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) - { - *prdest = *prsrc; - } - prdest++; - prsrc++; - } - } else { - /* ABGR\ARGB subpixel order - Alpha byte is first */ - while (prdest < max_ptr) { - if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) - { - *prdest = *prsrc; - } - prdest++; - prsrc++; - } - } - - /* Grayscale ontop of RGB24 - complete */ - } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_GRAY8 ) { - const uint8_t* const max_ptr = buffer+size; - const uint8_t* psrc = image.buffer; - uint8_t* pdest = buffer; - - while( pdest < max_ptr ) - { - if ( *psrc ) - { - RED_PTR_RGBA(pdest) = GREEN_PTR_RGBA(pdest) = BLUE_PTR_RGBA(pdest) = *psrc; - } - pdest += 3; - psrc++; - } - - /* RGB24 ontop of RGB24 - not complete. need to take care of different subpixel orders */ - } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB24 ) { - const uint8_t* const max_ptr = buffer+size; - const uint8_t* psrc = image.buffer; - uint8_t* pdest = buffer; - - while( pdest < max_ptr ) - { - if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) - { - RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); - GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); - BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); - } - pdest += 3; - psrc += 3; - } - - /* RGB32 ontop of RGB24 - TO BE DONE */ - } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB32 ) { - Error("Overlay of RGB32 ontop of RGB24 is not supported."); - - /* Grayscale ontop of RGB32 - complete */ - } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_GRAY8 ) { - const Rgb* const max_ptr = (Rgb*)(buffer+size); - Rgb* prdest = (Rgb*)buffer; - const uint8_t* psrc = image.buffer; - - if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* RGBA\BGRA subpixel order - Alpha byte is last */ - while (prdest < max_ptr) { - if ( *psrc ) - { - RED_PTR_RGBA(prdest) = GREEN_PTR_RGBA(prdest) = BLUE_PTR_RGBA(prdest) = *psrc; - } - prdest++; - psrc++; - } - } else { - /* ABGR\ARGB subpixel order - Alpha byte is first */ - while (prdest < max_ptr) { - if ( *psrc ) - { - RED_PTR_ABGR(prdest) = GREEN_PTR_ABGR(prdest) = BLUE_PTR_ABGR(prdest) = *psrc; - } - prdest++; - psrc++; - } - } - - /* RGB24 ontop of RGB32 - TO BE DONE */ - } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB24 ) { - Error("Overlay of RGB24 ontop of RGB32 is not supported."); - - /* RGB32 ontop of RGB32 - not complete. need to take care of different subpixel orders */ - } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB32 ) { - const Rgb* const max_ptr = (Rgb*)(buffer+size); - Rgb* prdest = (Rgb*)buffer; - const Rgb* prsrc = (Rgb*)image.buffer; - - if(image.subpixelorder == ZM_SUBPIX_ORDER_RGBA || image.subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ - while (prdest < max_ptr) { - if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) - { - *prdest = *prsrc; - } - prdest++; - prsrc++; - } - } else { - /* ABGR\ARGB subpixel order - Alpha byte is first */ - while (prdest < max_ptr) { - if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) - { - *prdest = *prsrc; - } - prdest++; - prsrc++; - } - } - } - + if ( !(width == image.width && height == image.height) ) + { + Panic( "Attempt to overlay different sized images, expected %dx%d, got %dx%d", width, height, image.width, image.height ); + } + + if( colours == image.colours && subpixelorder != image.subpixelorder ) { + Warning("Attempt to overlay images of same format but with different subpixel order."); + } + + /* Grayscale ontop of grayscale - complete */ + if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_GRAY8 ) { + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( *psrc ) + { + *pdest = *psrc; + } + pdest++; + psrc++; + } + + /* RGB24 ontop of grayscale - convert to same format first - complete */ + } else if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB24 ) { + Colourise(image.colours, image.subpixelorder); + + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) + { + RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); + GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); + BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); + } + pdest += 3; + psrc += 3; + } + + /* RGB32 ontop of grayscale - convert to same format first - complete */ + } else if( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB32 ) { + Colourise(image.colours, image.subpixelorder); + + const Rgb* const max_ptr = (Rgb*)(buffer+size); + const Rgb* prsrc = (Rgb*)image.buffer; + Rgb* prdest = (Rgb*)buffer; + + if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ + while (prdest < max_ptr) { + if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } else { + /* ABGR\ARGB subpixel order - Alpha byte is first */ + while (prdest < max_ptr) { + if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } + + /* Grayscale ontop of RGB24 - complete */ + } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_GRAY8 ) { + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( *psrc ) + { + RED_PTR_RGBA(pdest) = GREEN_PTR_RGBA(pdest) = BLUE_PTR_RGBA(pdest) = *psrc; + } + pdest += 3; + psrc++; + } + + /* RGB24 ontop of RGB24 - not complete. need to take care of different subpixel orders */ + } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB24 ) { + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) + { + RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); + GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); + BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); + } + pdest += 3; + psrc += 3; + } + + /* RGB32 ontop of RGB24 - TO BE DONE */ + } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB32 ) { + Error("Overlay of RGB32 ontop of RGB24 is not supported."); + + /* Grayscale ontop of RGB32 - complete */ + } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_GRAY8 ) { + const Rgb* const max_ptr = (Rgb*)(buffer+size); + Rgb* prdest = (Rgb*)buffer; + const uint8_t* psrc = image.buffer; + + if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* RGBA\BGRA subpixel order - Alpha byte is last */ + while (prdest < max_ptr) { + if ( *psrc ) + { + RED_PTR_RGBA(prdest) = GREEN_PTR_RGBA(prdest) = BLUE_PTR_RGBA(prdest) = *psrc; + } + prdest++; + psrc++; + } + } else { + /* ABGR\ARGB subpixel order - Alpha byte is first */ + while (prdest < max_ptr) { + if ( *psrc ) + { + RED_PTR_ABGR(prdest) = GREEN_PTR_ABGR(prdest) = BLUE_PTR_ABGR(prdest) = *psrc; + } + prdest++; + psrc++; + } + } + + /* RGB24 ontop of RGB32 - TO BE DONE */ + } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB24 ) { + Error("Overlay of RGB24 ontop of RGB32 is not supported."); + + /* RGB32 ontop of RGB32 - not complete. need to take care of different subpixel orders */ + } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB32 ) { + const Rgb* const max_ptr = (Rgb*)(buffer+size); + Rgb* prdest = (Rgb*)buffer; + const Rgb* prsrc = (Rgb*)image.buffer; + + if(image.subpixelorder == ZM_SUBPIX_ORDER_RGBA || image.subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ + while (prdest < max_ptr) { + if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } else { + /* ABGR\ARGB subpixel order - Alpha byte is first */ + while (prdest < max_ptr) { + if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } + } + } /* RGB32 compatible: complete */ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) { - if ( !(width < image.width || height < image.height) ) - { - Panic( "Attempt to overlay image too big for destination, %dx%d > %dx%d", image.width, image.height, width, height ); - } + if ( !(width < image.width || height < image.height) ) + { + Panic( "Attempt to overlay image too big for destination, %dx%d > %dx%d", image.width, image.height, width, height ); + } - if ( !(width < (x+image.width) || height < (y+image.height)) ) - { - Panic( "Attempt to overlay image outside of destination bounds, %dx%d @ %dx%d > %dx%d", image.width, image.height, x, y, width, height ); - } + if ( !(width < (x+image.width) || height < (y+image.height)) ) + { + Panic( "Attempt to overlay image outside of destination bounds, %dx%d @ %dx%d > %dx%d", image.width, image.height, x, y, width, height ); + } - if ( !(colours == image.colours) ) - { - Panic( "Attempt to partial overlay differently coloured images, expected %d, got %d", colours, image.colours ); - } + if ( !(colours == image.colours) ) + { + Panic( "Attempt to partial overlay differently coloured images, expected %d, got %d", colours, image.colours ); + } - unsigned int lo_x = x; - unsigned int lo_y = y; - unsigned int hi_x = (x+image.width)-1; - unsigned int hi_y = (y+image.height-1); - if ( colours == ZM_COLOUR_GRAY8 ) - { - const uint8_t *psrc = image.buffer; - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - uint8_t *pdest = &buffer[(y*width)+lo_x]; - for ( unsigned int x = lo_x; x <= hi_x; x++ ) - { - *pdest++ = *psrc++; - } - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - const uint8_t *psrc = image.buffer; - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - uint8_t *pdest = &buffer[colours*((y*width)+lo_x)]; - for ( unsigned int x = lo_x; x <= hi_x; x++ ) - { - *pdest++ = *psrc++; - *pdest++ = *psrc++; - *pdest++ = *psrc++; - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - const Rgb *psrc = (Rgb*)(image.buffer); - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - Rgb *pdest = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( unsigned int x = lo_x; x <= hi_x; x++ ) - { - *pdest++ = *psrc++; - } - } - } else { - Error("Overlay called with unexpected colours: %d", colours); - } - + unsigned int lo_x = x; + unsigned int lo_y = y; + unsigned int hi_x = (x+image.width)-1; + unsigned int hi_y = (y+image.height-1); + if ( colours == ZM_COLOUR_GRAY8 ) + { + const uint8_t *psrc = image.buffer; + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + uint8_t *pdest = &buffer[(y*width)+lo_x]; + for ( unsigned int x = lo_x; x <= hi_x; x++ ) + { + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + const uint8_t *psrc = image.buffer; + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + uint8_t *pdest = &buffer[colours*((y*width)+lo_x)]; + for ( unsigned int x = lo_x; x <= hi_x; x++ ) + { + *pdest++ = *psrc++; + *pdest++ = *psrc++; + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + const Rgb *psrc = (Rgb*)(image.buffer); + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + Rgb *pdest = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + for ( unsigned int x = lo_x; x <= hi_x; x++ ) + { + *pdest++ = *psrc++; + } + } + } else { + Error("Overlay called with unexpected colours: %d", colours); + } + } void Image::Blend( const Image &image, int transparency ) { #ifdef ZM_IMAGE_PROFILING - struct timespec start,end,diff; - unsigned long long executetime; - unsigned long milpixels; + struct timespec start,end,diff; + unsigned long long executetime; + unsigned long milpixels; #endif - uint8_t* new_buffer; - - if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) - { - Panic( "Attempt to blend different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder ); - } - - if(transparency <= 0) - return; - - new_buffer = AllocBuffer(size); - + uint8_t* new_buffer; + + if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) + { + Panic( "Attempt to blend different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder ); + } + + if(transparency <= 0) + return; + + new_buffer = AllocBuffer(size); + #ifdef ZM_IMAGE_PROFILING - clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start); + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start); #endif - - /* Do the blending */ - (*fptr_blend)(buffer, image.buffer, new_buffer, size, transparency); - + + /* Do the blending */ + (*fptr_blend)(buffer, image.buffer, new_buffer, size, transparency); + #ifdef ZM_IMAGE_PROFILING - clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end); - timespec_diff(&start,&end,&diff); - - executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec; - milpixels = (unsigned long)((long double)size)/((((long double)executetime)/1000)); - Debug(5, "Blend: %u colours blended in %llu nanoseconds, %lu million colours/s\n",size,executetime,milpixels); + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end); + timespec_diff(&start,&end,&diff); + + executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec; + milpixels = (unsigned long)((long double)size)/((((long double)executetime)/1000)); + Debug(5, "Blend: %u colours blended in %llu nanoseconds, %lu million colours/s\n",size,executetime,milpixels); #endif - - AssignDirect( width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM); + + AssignDirect( width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM); } Image *Image::Merge( unsigned int n_images, Image *images[] ) { - if ( n_images <= 0 ) return( 0 ); - if ( n_images == 1 ) return( new Image( *images[0] ) ); + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); - unsigned int width = images[0]->width; - unsigned int height = images[0]->height; - unsigned int colours = images[0]->colours; - for ( unsigned int i = 1; i < n_images; i++ ) - { - if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) - { - Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); - } - } + unsigned int width = images[0]->width; + unsigned int height = images[0]->height; + unsigned int colours = images[0]->colours; + for ( unsigned int i = 1; i < n_images; i++ ) + { + if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) + { + Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + } + } - Image *result = new Image( width, height, images[0]->colours, images[0]->subpixelorder); - unsigned int size = result->size; - for ( unsigned int i = 0; i < size; i++ ) - { - unsigned int total = 0; - uint8_t *pdest = result->buffer; - for ( unsigned int j = 0; j < n_images; j++ ) - { - uint8_t *psrc = images[j]->buffer; - total += *psrc; - psrc++; - } - *pdest = total/n_images; - pdest++; - } - return( result ); + Image *result = new Image( width, height, images[0]->colours, images[0]->subpixelorder); + unsigned int size = result->size; + for ( unsigned int i = 0; i < size; i++ ) + { + unsigned int total = 0; + uint8_t *pdest = result->buffer; + for ( unsigned int j = 0; j < n_images; j++ ) + { + uint8_t *psrc = images[j]->buffer; + total += *psrc; + psrc++; + } + *pdest = total/n_images; + pdest++; + } + return( result ); } Image *Image::Merge( unsigned int n_images, Image *images[], double weight ) { - if ( n_images <= 0 ) return( 0 ); - if ( n_images == 1 ) return( new Image( *images[0] ) ); + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); - unsigned int width = images[0]->width; - unsigned int height = images[0]->height; - unsigned int colours = images[0]->colours; - for ( unsigned int i = 1; i < n_images; i++ ) - { - if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) - { - Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); - } - } + unsigned int width = images[0]->width; + unsigned int height = images[0]->height; + unsigned int colours = images[0]->colours; + for ( unsigned int i = 1; i < n_images; i++ ) + { + if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) + { + Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + } + } - Image *result = new Image( *images[0] ); - unsigned int size = result->size; - double factor = 1.0*weight; - for ( unsigned int i = 1; i < n_images; i++ ) - { - uint8_t *pdest = result->buffer; - uint8_t *psrc = images[i]->buffer; - for ( unsigned int j = 0; j < size; j++ ) - { - *pdest = (uint8_t)(((*pdest)*(1.0-factor))+((*psrc)*factor)); - pdest++; - psrc++; - } - factor *= weight; - } - return( result ); + Image *result = new Image( *images[0] ); + unsigned int size = result->size; + double factor = 1.0*weight; + for ( unsigned int i = 1; i < n_images; i++ ) + { + uint8_t *pdest = result->buffer; + uint8_t *psrc = images[i]->buffer; + for ( unsigned int j = 0; j < size; j++ ) + { + *pdest = (uint8_t)(((*pdest)*(1.0-factor))+((*psrc)*factor)); + pdest++; + psrc++; + } + factor *= weight; + } + return( result ); } Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb threshold, const Rgb ref_colour ) { - if ( n_images <= 0 ) return( 0 ); - if ( n_images == 1 ) return( new Image( *images[0] ) ); + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); - unsigned int width = images[0]->width; - unsigned int height = images[0]->height; - unsigned int colours = images[0]->colours; - for ( unsigned int i = 1; i < n_images; i++ ) - { - if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) - { - Panic( "Attempt to highlight different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); - } - } + unsigned int width = images[0]->width; + unsigned int height = images[0]->height; + unsigned int colours = images[0]->colours; + for ( unsigned int i = 1; i < n_images; i++ ) + { + if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) + { + Panic( "Attempt to highlight different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + } + } - Image *result = new Image( width, height, images[0]->colours, images[0]->subpixelorder ); - unsigned int size = result->size; - for ( unsigned int c = 0; c < colours; c++ ) - { - for ( unsigned int i = 0; i < size; i++ ) - { - unsigned int count = 0; - uint8_t *pdest = result->buffer+c; - for ( unsigned int j = 0; j < n_images; j++ ) - { - uint8_t *psrc = images[j]->buffer+c; + Image *result = new Image( width, height, images[0]->colours, images[0]->subpixelorder ); + unsigned int size = result->size; + for ( unsigned int c = 0; c < colours; c++ ) + { + for ( unsigned int i = 0; i < size; i++ ) + { + unsigned int count = 0; + uint8_t *pdest = result->buffer+c; + for ( unsigned int j = 0; j < n_images; j++ ) + { + uint8_t *psrc = images[j]->buffer+c; #ifndef SOLARIS - if ( (unsigned)abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) ) + if ( (unsigned)abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) ) #else - if ( (unsigned)std::abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) ) + if ( (unsigned)std::abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) ) #endif - { - count++; - } - psrc += colours; - } - *pdest = (count*255)/n_images; - pdest += 3; - } - } - return( result ); + { + count++; + } + psrc += colours; + } + *pdest = (count*255)/n_images; + pdest += 3; + } + } + return( result ); } /* New function to allow buffer re-using instead of allocationg memory for the delta image every time */ void Image::Delta( const Image &image, Image* targetimage) const { #ifdef ZM_IMAGE_PROFILING - struct timespec start,end,diff; - unsigned long long executetime; - unsigned long milpixels; + struct timespec start,end,diff; + unsigned long long executetime; + unsigned long milpixels; #endif - - if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) - { - Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder); - } - - uint8_t *pdiff = targetimage->WriteBuffer(width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE); - - if(pdiff == NULL) { - Panic("Failed requesting writeable buffer for storing the delta image"); - } - + + if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) + { + Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder); + } + + uint8_t *pdiff = targetimage->WriteBuffer(width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE); + + if(pdiff == NULL) { + Panic("Failed requesting writeable buffer for storing the delta image"); + } + #ifdef ZM_IMAGE_PROFILING - clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start); + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start); #endif - - switch(colours) { - case ZM_COLOUR_RGB24: - { - if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { - /* BGR subpixel order */ - (*fptr_delta8_bgr)(buffer, image.buffer, pdiff, pixels); - } else { - /* Assume RGB subpixel order */ - (*fptr_delta8_rgb)(buffer, image.buffer, pdiff, pixels); - } - break; - } - case ZM_COLOUR_RGB32: - { - if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - /* ARGB subpixel order */ - (*fptr_delta8_argb)(buffer, image.buffer, pdiff, pixels); - } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - /* ABGR subpixel order */ - (*fptr_delta8_abgr)(buffer, image.buffer, pdiff, pixels); - } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* BGRA subpixel order */ - (*fptr_delta8_bgra)(buffer, image.buffer, pdiff, pixels); - } else { - /* Assume RGBA subpixel order */ - (*fptr_delta8_rgba)(buffer, image.buffer, pdiff, pixels); - } - break; - } - case ZM_COLOUR_GRAY8: - (*fptr_delta8_gray8)(buffer, image.buffer, pdiff, pixels); - break; - default: - Panic("Delta called with unexpected colours: %d",colours); - break; - } - + + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + (*fptr_delta8_bgr)(buffer, image.buffer, pdiff, pixels); + } else { + /* Assume RGB subpixel order */ + (*fptr_delta8_rgb)(buffer, image.buffer, pdiff, pixels); + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + (*fptr_delta8_argb)(buffer, image.buffer, pdiff, pixels); + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + (*fptr_delta8_abgr)(buffer, image.buffer, pdiff, pixels); + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + (*fptr_delta8_bgra)(buffer, image.buffer, pdiff, pixels); + } else { + /* Assume RGBA subpixel order */ + (*fptr_delta8_rgba)(buffer, image.buffer, pdiff, pixels); + } + break; + } + case ZM_COLOUR_GRAY8: + (*fptr_delta8_gray8)(buffer, image.buffer, pdiff, pixels); + break; + default: + Panic("Delta called with unexpected colours: %d",colours); + break; + } + #ifdef ZM_IMAGE_PROFILING - clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end); - timespec_diff(&start,&end,&diff); - - executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec; - milpixels = (unsigned long)((long double)pixels)/((((long double)executetime)/1000)); - Debug(5, "Delta: %u delta pixels generated in %llu nanoseconds, %lu million pixels/s\n",pixels,executetime,milpixels); + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end); + timespec_diff(&start,&end,&diff); + + executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec; + milpixels = (unsigned long)((long double)pixels)/((((long double)executetime)/1000)); + Debug(5, "Delta: %u delta pixels generated in %llu nanoseconds, %lu million pixels/s\n",pixels,executetime,milpixels); #endif } const Coord Image::centreCoord( const char *text ) const { - int index = 0; - int line_no = 0; - int text_len = strlen( text ); - int line_len = 0; - int max_line_len = 0; - const char *line = text; + int index = 0; + int line_no = 0; + int text_len = strlen( text ); + int line_len = 0; + int max_line_len = 0; + const char *line = text; - while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) + while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) + { + if ( line_len > max_line_len ) + max_line_len = line_len; + + index += line_len; + while ( text[index] == '\n' ) { - if ( line_len > max_line_len ) - max_line_len = line_len; - - index += line_len; - while ( text[index] == '\n' ) - { - index++; - } - line = text+index; - line_no++; + index++; } - int x = (width - (max_line_len * CHAR_WIDTH) ) / 2; - int y = (height - (line_no * LINE_HEIGHT) ) / 2; - return( Coord( x, y ) ); + line = text+index; + line_no++; + } + int x = (width - (max_line_len * CHAR_WIDTH) ) / 2; + int y = (height - (line_no * LINE_HEIGHT) ) / 2; + return( Coord( x, y ) ); } /* RGB32 compatible: complete */ void Image::MaskPrivacy( const unsigned char *p_bitmask, const Rgb pixel_colour ) { - const uint8_t pixel_r_col = RED_VAL_RGBA(pixel_colour); - const uint8_t pixel_g_col = GREEN_VAL_RGBA(pixel_colour); - const uint8_t pixel_b_col = BLUE_VAL_RGBA(pixel_colour); - const uint8_t pixel_bw_col = pixel_colour & 0xff; - const Rgb pixel_rgb_col = rgb_convert(pixel_colour,subpixelorder); + const uint8_t pixel_r_col = RED_VAL_RGBA(pixel_colour); + const uint8_t pixel_g_col = GREEN_VAL_RGBA(pixel_colour); + const uint8_t pixel_b_col = BLUE_VAL_RGBA(pixel_colour); + const uint8_t pixel_bw_col = pixel_colour & 0xff; + const Rgb pixel_rgb_col = rgb_convert(pixel_colour,subpixelorder); - unsigned char *ptr = &buffer[0]; - unsigned int i = 0; + unsigned char *ptr = &buffer[0]; + unsigned int i = 0; - for ( unsigned int y = 0; y < height; y++ ) + for ( unsigned int y = 0; y < height; y++ ) + { + if ( colours == ZM_COLOUR_GRAY8 ) { - if ( colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int x = 0; x < width; x++, ptr++ ) - { - if ( p_bitmask[i] ) - *ptr = pixel_bw_col; - i++; - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int x = 0; x < width; x++, ptr += colours ) - { - if ( p_bitmask[i] ) - { - RED_PTR_RGBA(ptr) = pixel_r_col; - GREEN_PTR_RGBA(ptr) = pixel_g_col; - BLUE_PTR_RGBA(ptr) = pixel_b_col; - } - i++; - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for ( unsigned int x = 0; x < width; x++, ptr += colours ) - { - Rgb *temp_ptr = (Rgb*)ptr; - if ( p_bitmask[i] ) - *temp_ptr = pixel_rgb_col; - i++; - } - } else { - Panic("MaskPrivacy called with unexpected colours: %d", colours); - return; - } - + for ( unsigned int x = 0; x < width; x++, ptr++ ) + { + if ( p_bitmask[i] ) + *ptr = pixel_bw_col; + i++; + } } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for ( unsigned int x = 0; x < width; x++, ptr += colours ) + { + if ( p_bitmask[i] ) + { + RED_PTR_RGBA(ptr) = pixel_r_col; + GREEN_PTR_RGBA(ptr) = pixel_g_col; + BLUE_PTR_RGBA(ptr) = pixel_b_col; + } + i++; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for ( unsigned int x = 0; x < width; x++, ptr += colours ) + { + Rgb *temp_ptr = (Rgb*)ptr; + if ( p_bitmask[i] ) + *temp_ptr = pixel_rgb_col; + i++; + } + } else { + Panic("MaskPrivacy called with unexpected colours: %d", colours); + return; + } + + } } /* RGB32 compatible: complete */ void Image::Annotate( const char *p_text, const Coord &coord, const unsigned int size, const Rgb fg_colour, const Rgb bg_colour ) { - strncpy( text, p_text, sizeof(text) ); + strncpy( text, p_text, sizeof(text) ); - unsigned int index = 0; - unsigned int line_no = 0; - unsigned int text_len = strlen( text ); - unsigned int line_len = 0; - const char *line = text; + unsigned int index = 0; + unsigned int line_no = 0; + unsigned int text_len = strlen( text ); + unsigned int line_len = 0; + const char *line = text; - const uint8_t fg_r_col = RED_VAL_RGBA(fg_colour); - const uint8_t fg_g_col = GREEN_VAL_RGBA(fg_colour); - const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour); - const uint8_t fg_bw_col = fg_colour & 0xff; - const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder); - const bool fg_trans = (fg_colour == RGB_TRANSPARENT); - - const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour); - const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour); - const uint8_t bg_b_col = BLUE_VAL_RGBA(bg_colour); - const uint8_t bg_bw_col = bg_colour & 0xff; - const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder); - const bool bg_trans = (bg_colour == RGB_TRANSPARENT); + const uint8_t fg_r_col = RED_VAL_RGBA(fg_colour); + const uint8_t fg_g_col = GREEN_VAL_RGBA(fg_colour); + const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour); + const uint8_t fg_bw_col = fg_colour & 0xff; + const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder); + const bool fg_trans = (fg_colour == RGB_TRANSPARENT); + + const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour); + const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour); + const uint8_t bg_b_col = BLUE_VAL_RGBA(bg_colour); + const uint8_t bg_bw_col = bg_colour & 0xff; + const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder); + const bool bg_trans = (bg_colour == RGB_TRANSPARENT); - int zm_text_bitmask = 0x80; - if (size == 2) - zm_text_bitmask = 0x8000; + int zm_text_bitmask = 0x80; + if (size == 2) + zm_text_bitmask = 0x8000; - while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) + while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) + { + + unsigned int line_width = line_len * CHAR_WIDTH * size; + + unsigned int lo_line_x = coord.X(); + unsigned int lo_line_y = coord.Y() + (line_no * LINE_HEIGHT * size); + + unsigned int min_line_x = 0; + unsigned int max_line_x = width - line_width; + unsigned int min_line_y = 0; + unsigned int max_line_y = height - (LINE_HEIGHT * size); + + if ( lo_line_x > max_line_x ) + lo_line_x = max_line_x; + if ( lo_line_x < min_line_x ) + lo_line_x = min_line_x; + if ( lo_line_y > max_line_y ) + lo_line_y = max_line_y; + if ( lo_line_y < min_line_y ) + lo_line_y = min_line_y; + + unsigned int hi_line_x = lo_line_x + line_width; + unsigned int hi_line_y = lo_line_y + (LINE_HEIGHT * size); + + // Clip anything that runs off the right of the screen + if ( hi_line_x > width ) + hi_line_x = width; + if ( hi_line_y > height ) + hi_line_y = height; + + if ( colours == ZM_COLOUR_GRAY8 ) { - - unsigned int line_width = line_len * CHAR_WIDTH * size; - - unsigned int lo_line_x = coord.X(); - unsigned int lo_line_y = coord.Y() + (line_no * LINE_HEIGHT * size); - - unsigned int min_line_x = 0; - unsigned int max_line_x = width - line_width; - unsigned int min_line_y = 0; - unsigned int max_line_y = height - (LINE_HEIGHT * size); - - if ( lo_line_x > max_line_x ) - lo_line_x = max_line_x; - if ( lo_line_x < min_line_x ) - lo_line_x = min_line_x; - if ( lo_line_y > max_line_y ) - lo_line_y = max_line_y; - if ( lo_line_y < min_line_y ) - lo_line_y = min_line_y; - - unsigned int hi_line_x = lo_line_x + line_width; - unsigned int hi_line_y = lo_line_y + (LINE_HEIGHT * size); - - // Clip anything that runs off the right of the screen - if ( hi_line_x > width ) - hi_line_x = width; - if ( hi_line_y > height ) - hi_line_y = height; - - if ( colours == ZM_COLOUR_GRAY8 ) + unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x]; + for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (CHAR_HEIGHT * size); y++, r++, ptr += width ) + { + unsigned char *temp_ptr = ptr; + for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) { - unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x]; - for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (CHAR_HEIGHT * size); y++, r++, ptr += width ) + int f; + if (size == 2) + f = bigfontdata[(line[c] * CHAR_HEIGHT * size) + r]; + else + f = fontdata[(line[c] * CHAR_HEIGHT) + r]; + for ( unsigned int i = 0; i < (CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) + { + if ( f & (zm_text_bitmask >> i) ) { - unsigned char *temp_ptr = ptr; - for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) - { - int f; - if (size == 2) - f = bigfontdata[(line[c] * CHAR_HEIGHT * size) + r]; - else - f = fontdata[(line[c] * CHAR_HEIGHT) + r]; - for ( unsigned int i = 0; i < (CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) - { - if ( f & (zm_text_bitmask >> i) ) - { - if ( !fg_trans ) - *temp_ptr = fg_bw_col; - } - else if ( !bg_trans ) - { - *temp_ptr = bg_bw_col; - } - } - } + if ( !fg_trans ) + *temp_ptr = fg_bw_col; } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - unsigned int wc = width * colours; - - unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours]; - for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (CHAR_HEIGHT * size); y++, r++, ptr += wc ) + else if ( !bg_trans ) { - unsigned char *temp_ptr = ptr; - for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) - { - int f; - if (size == 2) - f = bigfontdata[(line[c] * CHAR_HEIGHT * size) + r]; - else - f = fontdata[(line[c] * CHAR_HEIGHT) + r]; - for ( unsigned int i = 0; i < (CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) - { - if ( f & (zm_text_bitmask >> i) ) - { - if ( !fg_trans ) - { - RED_PTR_RGBA(temp_ptr) = fg_r_col; - GREEN_PTR_RGBA(temp_ptr) = fg_g_col; - BLUE_PTR_RGBA(temp_ptr) = fg_b_col; - } - } - else if ( !bg_trans ) - { - RED_PTR_RGBA(temp_ptr) = bg_r_col; - GREEN_PTR_RGBA(temp_ptr) = bg_g_col; - BLUE_PTR_RGBA(temp_ptr) = bg_b_col; - } - } - } + *temp_ptr = bg_bw_col; } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - unsigned int wc = width * colours; - - uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x)<<2]; - for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (CHAR_HEIGHT * size); y++, r++, ptr += wc ) - { - Rgb* temp_ptr = (Rgb*)ptr; - for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) - { - int f; - if (size == 2) - f = bigfontdata[(line[c] * CHAR_HEIGHT * size) + r]; - else - f = fontdata[(line[c] * CHAR_HEIGHT) + r]; - for ( unsigned int i = 0; i < (CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) - { - if ( f & (zm_text_bitmask >> i) ) - { - if ( !fg_trans ) - { - *temp_ptr = fg_rgb_col; - } - } - else if ( !bg_trans ) - { - *temp_ptr = bg_rgb_col; - } - } - } - } - - } else { - Panic("Annotate called with unexpected colours: %d",colours); - return; - } - - index += line_len; - while ( text[index] == '\n' ) - { - index++; + } } - line = text+index; - line_no++; + } } + else if ( colours == ZM_COLOUR_RGB24 ) + { + unsigned int wc = width * colours; + + unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours]; + for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (CHAR_HEIGHT * size); y++, r++, ptr += wc ) + { + unsigned char *temp_ptr = ptr; + for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) + { + int f; + if (size == 2) + f = bigfontdata[(line[c] * CHAR_HEIGHT * size) + r]; + else + f = fontdata[(line[c] * CHAR_HEIGHT) + r]; + for ( unsigned int i = 0; i < (CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr += colours ) + { + if ( f & (zm_text_bitmask >> i) ) + { + if ( !fg_trans ) + { + RED_PTR_RGBA(temp_ptr) = fg_r_col; + GREEN_PTR_RGBA(temp_ptr) = fg_g_col; + BLUE_PTR_RGBA(temp_ptr) = fg_b_col; + } + } + else if ( !bg_trans ) + { + RED_PTR_RGBA(temp_ptr) = bg_r_col; + GREEN_PTR_RGBA(temp_ptr) = bg_g_col; + BLUE_PTR_RGBA(temp_ptr) = bg_b_col; + } + } + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + unsigned int wc = width * colours; + + uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x)<<2]; + for ( unsigned int y = lo_line_y, r = 0; y < hi_line_y && r < (CHAR_HEIGHT * size); y++, r++, ptr += wc ) + { + Rgb* temp_ptr = (Rgb*)ptr; + for ( unsigned int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) + { + int f; + if (size == 2) + f = bigfontdata[(line[c] * CHAR_HEIGHT * size) + r]; + else + f = fontdata[(line[c] * CHAR_HEIGHT) + r]; + for ( unsigned int i = 0; i < (CHAR_WIDTH * size) && x < hi_line_x; i++, x++, temp_ptr++ ) + { + if ( f & (zm_text_bitmask >> i) ) + { + if ( !fg_trans ) + { + *temp_ptr = fg_rgb_col; + } + } + else if ( !bg_trans ) + { + *temp_ptr = bg_rgb_col; + } + } + } + } + + } else { + Panic("Annotate called with unexpected colours: %d",colours); + return; + } + + index += line_len; + while ( text[index] == '\n' ) + { + index++; + } + line = text+index; + line_no++; + } } void Image::Timestamp( const char *label, const time_t when, const Coord &coord, const int size ) { - char time_text[64]; - strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) ); - char text[64]; - if ( label ) - { - snprintf( text, sizeof(text), "%s - %s", label, time_text ); - Annotate( text, coord, size ); - } - else - { - Annotate( time_text, coord, size ); - } + char time_text[64]; + strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) ); + char text[64]; + if ( label ) + { + snprintf( text, sizeof(text), "%s - %s", label, time_text ); + Annotate( text, coord, size ); + } + else + { + Annotate( time_text, coord, size ); + } } /* RGB32 compatible: complete */ void Image::Colourise(const unsigned int p_reqcolours, const unsigned int p_reqsubpixelorder) { - Debug(9, "Colourise: Req colours: %u Req subpixel order: %u Current colours: %u Current subpixel order: %u",p_reqcolours,p_reqsubpixelorder,colours,subpixelorder); - - if ( colours != ZM_COLOUR_GRAY8) { - Warning("Target image is already colourised, colours: %u",colours); - return; - } - - if ( p_reqcolours == ZM_COLOUR_RGB32 ) { - /* RGB32 */ - Rgb* new_buffer = (Rgb*)AllocBuffer(pixels*sizeof(Rgb)); - - const uint8_t *psrc = buffer; - Rgb* pdest = new_buffer; - Rgb subpixel; - Rgb newpixel; - - if ( p_reqsubpixelorder == ZM_SUBPIX_ORDER_ABGR || p_reqsubpixelorder == ZM_SUBPIX_ORDER_ARGB) { - /* ARGB\ABGR subpixel order. alpha byte is first (mem+0), so we need to shift the pixel left in the end */ - for(unsigned int i=0;iLo().X():0; - unsigned int lo_y = limits?limits->Lo().Y():0; - unsigned int hi_x = limits?limits->Hi().X():width-1; - unsigned int hi_y = limits?limits->Hi().Y():height-1; - if ( colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - unsigned char *p = &buffer[(y*width)+lo_x]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++) - { - *p = colour; - } - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - unsigned char *p = &buffer[colours*((y*width)+lo_x)]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) - { - RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); - GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); - BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ - { - for ( unsigned int y = lo_y; y <= (unsigned int)hi_y; y++ ) - { - Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - - for ( unsigned int x = lo_x; x <= (unsigned int)hi_x; x++, p++) - { - /* Fast, copies the entire pixel in a single pass */ - *p = colour; - } - } - } + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) + { + Panic( "Attempt to fill image with unexpected colours %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,subpixelorder); + + unsigned int lo_x = limits?limits->Lo().X():0; + unsigned int lo_y = limits?limits->Lo().Y():0; + unsigned int hi_x = limits?limits->Hi().X():width-1; + unsigned int hi_y = limits?limits->Hi().Y():height-1; + if ( colours == ZM_COLOUR_GRAY8 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[(y*width)+lo_x]; + for ( unsigned int x = lo_x; x <= hi_x; x++, p++) + { + *p = colour; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[colours*((y*width)+lo_x)]; + for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) + { + RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ + { + for ( unsigned int y = lo_y; y <= (unsigned int)hi_y; y++ ) + { + Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + + for ( unsigned int x = lo_x; x <= (unsigned int)hi_x; x++, p++) + { + /* Fast, copies the entire pixel in a single pass */ + *p = colour; + } + } + } } /* RGB32 compatible: complete */ void Image::Fill( Rgb colour, int density, const Box *limits ) { - /* Allow the faster version to be used if density is not used (density=1) */ - if(density <= 1) - return Fill(colour,limits); - - if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) - { - Panic( "Attempt to fill image with unexpected colours %d", colours ); - } - - /* Convert the colour's RGBA subpixel order into the image's subpixel order */ - colour = rgb_convert(colour,subpixelorder); + /* Allow the faster version to be used if density is not used (density=1) */ + if(density <= 1) + return Fill(colour,limits); + + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) + { + Panic( "Attempt to fill image with unexpected colours %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,subpixelorder); - unsigned int lo_x = limits?limits->Lo().X():0; - unsigned int lo_y = limits?limits->Lo().Y():0; - unsigned int hi_x = limits?limits->Hi().X():width-1; - unsigned int hi_y = limits?limits->Hi().Y():height-1; - if ( colours == ZM_COLOUR_GRAY8 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - unsigned char *p = &buffer[(y*width)+lo_x]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++) - { - if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) - *p = colour; - } - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - unsigned char *p = &buffer[colours*((y*width)+lo_x)]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) - { - if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) { - RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); - GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); - BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); - } - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ - { - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - Rgb* p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + unsigned int lo_x = limits?limits->Lo().X():0; + unsigned int lo_y = limits?limits->Lo().Y():0; + unsigned int hi_x = limits?limits->Hi().X():width-1; + unsigned int hi_y = limits?limits->Hi().Y():height-1; + if ( colours == ZM_COLOUR_GRAY8 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[(y*width)+lo_x]; + for ( unsigned int x = lo_x; x <= hi_x; x++, p++) + { + if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) + *p = colour; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[colours*((y*width)+lo_x)]; + for ( unsigned int x = lo_x; x <= hi_x; x++, p += 3) + { + if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) { + RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); + } + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ + { + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + Rgb* p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( unsigned int x = lo_x; x <= hi_x; x++, p++) - { - if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) - /* Fast, copies the entire pixel in a single pass */ - *p = colour; - } - } - } - + for ( unsigned int x = lo_x; x <= hi_x; x++, p++) + { + if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) + /* Fast, copies the entire pixel in a single pass */ + *p = colour; + } + } + } + } /* RGB32 compatible: complete */ void Image::Outline( Rgb colour, const Polygon &polygon ) { - if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) - { - Panic( "Attempt to outline image with unexpected colours %d", colours ); - } - - /* Convert the colour's RGBA subpixel order into the image's subpixel order */ - colour = rgb_convert(colour,subpixelorder); - - int n_coords = polygon.getNumCoords(); - for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) - { - const Coord &p1 = polygon.getCoord( i ); - const Coord &p2 = polygon.getCoord( j ); + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) + { + Panic( "Attempt to outline image with unexpected colours %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,subpixelorder); + + int n_coords = polygon.getNumCoords(); + for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) + { + const Coord &p1 = polygon.getCoord( i ); + const Coord &p2 = polygon.getCoord( j ); - int x1 = p1.X(); - int x2 = p2.X(); - int y1 = p1.Y(); - int y2 = p2.Y(); + int x1 = p1.X(); + int x2 = p2.X(); + int y1 = p1.Y(); + int y2 = p2.Y(); - double dx = x2 - x1; - double dy = y2 - y1; + double dx = x2 - x1; + double dy = y2 - y1; - double grad; + double grad; - //Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy ); - if ( fabs(dx) <= fabs(dy) ) - { - //Debug( 9, "dx <= dy" ); - if ( y1 != y2 ) - grad = dx/dy; - else - grad = width; + //Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy ); + if ( fabs(dx) <= fabs(dy) ) + { + //Debug( 9, "dx <= dy" ); + if ( y1 != y2 ) + grad = dx/dy; + else + grad = width; - double x; - int y, yinc = (y1 dy" ); - if ( x1 != x2 ) - grad = dy/dx; - else - grad = height; - //Debug( 9, "grad: %.2lf", grad ); + double x; + int y, yinc = (y1 dy" ); + if ( x1 != x2 ) + grad = dy/dx; + else + grad = height; + //Debug( 9, "grad: %.2lf", grad ); - double y; - int x, xinc = (x1= Logger::DEBUG9 ) - { - for ( int i = 0; i < n_global_edges; i++ ) - { - Debug( 9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m ); - } - } + if ( logLevel() >= Logger::DEBUG9 ) + { + for ( int i = 0; i < n_global_edges; i++ ) + { + Debug( 9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m ); + } + } #endif - int n_active_edges = 0; - Edge active_edges[n_global_edges]; - int y = global_edges[0].min_y; - do - { - for ( int i = 0; i < n_global_edges; i++ ) - { - if ( global_edges[i].min_y == y ) - { - Debug( 9, "Moving global edge" ); - active_edges[n_active_edges++] = global_edges[i]; - if ( i < (n_global_edges-1) ) - { - //memcpy( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); - memmove( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); - i--; - } - n_global_edges--; - } - else - { - break; - } - } - qsort( active_edges, n_active_edges, sizeof(*active_edges), Edge::CompareX ); + int n_active_edges = 0; + Edge active_edges[n_global_edges]; + int y = global_edges[0].min_y; + do + { + for ( int i = 0; i < n_global_edges; i++ ) + { + if ( global_edges[i].min_y == y ) + { + Debug( 9, "Moving global edge" ); + active_edges[n_active_edges++] = global_edges[i]; + if ( i < (n_global_edges-1) ) + { + //memcpy( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); + memmove( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); + i--; + } + n_global_edges--; + } + else + { + break; + } + } + qsort( active_edges, n_active_edges, sizeof(*active_edges), Edge::CompareX ); #ifndef ZM_DBG_OFF - if ( logLevel() >= Logger::DEBUG9 ) - { - for ( int i = 0; i < n_active_edges; i++ ) - { - Debug( 9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m ); - } - } + if ( logLevel() >= Logger::DEBUG9 ) + { + for ( int i = 0; i < n_active_edges; i++ ) + { + Debug( 9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m ); + } + } #endif - if ( !(y%density) ) - { - //Debug( 9, "%d", y ); - for ( int i = 0; i < n_active_edges; ) - { - int lo_x = int(round(active_edges[i++].min_x)); - int hi_x = int(round(active_edges[i++].min_x)); - if( colours == ZM_COLOUR_GRAY8 ) { - unsigned char *p = &buffer[(y*width)+lo_x]; - for ( int x = lo_x; x <= hi_x; x++, p++) - { - if ( !(x%density) ) - { - //Debug( 9, " %d", x ); - *p = colour; - } - } - } else if( colours == ZM_COLOUR_RGB24 ) { - unsigned char *p = &buffer[colours*((y*width)+lo_x)]; - for ( int x = lo_x; x <= hi_x; x++, p += 3) - { - if ( !(x%density) ) - { - RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); - GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); - BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); - } - } - } else if( colours == ZM_COLOUR_RGB32 ) { - Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; - for ( int x = lo_x; x <= hi_x; x++, p++) - { - if ( !(x%density) ) - { - /* Fast, copies the entire pixel in a single pass */ - *p = colour; - } - } - } - } - } - y++; - for ( int i = n_active_edges-1; i >= 0; i-- ) - { - if ( y >= active_edges[i].max_y ) // Or >= as per sheets - { - Debug( 9, "Deleting active_edge" ); - if ( i < (n_active_edges-1) ) - { - //memcpy( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); - memmove( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); - } - n_active_edges--; - } - else - { - active_edges[i].min_x += active_edges[i]._1_m; - } - } - } while ( n_global_edges || n_active_edges ); + if ( !(y%density) ) + { + //Debug( 9, "%d", y ); + for ( int i = 0; i < n_active_edges; ) + { + int lo_x = int(round(active_edges[i++].min_x)); + int hi_x = int(round(active_edges[i++].min_x)); + if( colours == ZM_COLOUR_GRAY8 ) { + unsigned char *p = &buffer[(y*width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++, p++) + { + if ( !(x%density) ) + { + //Debug( 9, " %d", x ); + *p = colour; + } + } + } else if( colours == ZM_COLOUR_RGB24 ) { + unsigned char *p = &buffer[colours*((y*width)+lo_x)]; + for ( int x = lo_x; x <= hi_x; x++, p += 3) + { + if ( !(x%density) ) + { + RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); + } + } + } else if( colours == ZM_COLOUR_RGB32 ) { + Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + for ( int x = lo_x; x <= hi_x; x++, p++) + { + if ( !(x%density) ) + { + /* Fast, copies the entire pixel in a single pass */ + *p = colour; + } + } + } + } + } + y++; + for ( int i = n_active_edges-1; i >= 0; i-- ) + { + if ( y >= active_edges[i].max_y ) // Or >= as per sheets + { + Debug( 9, "Deleting active_edge" ); + if ( i < (n_active_edges-1) ) + { + //memcpy( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); + memmove( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); + } + n_active_edges--; + } + else + { + active_edges[i].min_x += active_edges[i]._1_m; + } + } + } while ( n_global_edges || n_active_edges ); } void Image::Fill( Rgb colour, const Polygon &polygon ) { - Fill( colour, 1, polygon ); + Fill( colour, 1, polygon ); } /* RGB32 compatible: complete */ void Image::Rotate( int angle ) { - - angle %= 360; + + angle %= 360; - if ( !angle ) - { - return; - } - if ( angle%90 ) - { - return; - } - - unsigned int new_height = height; - unsigned int new_width = width; - uint8_t* rotate_buffer = AllocBuffer(size); + if ( !angle ) + { + return; + } + if ( angle%90 ) + { + return; + } + + unsigned int new_height = height; + unsigned int new_width = width; + uint8_t* rotate_buffer = AllocBuffer(size); - switch( angle ) - { - case 90 : - { - new_height = width; - new_width = height; + switch( angle ) + { + case 90 : + { + new_height = width; + new_width = height; - unsigned int line_bytes = new_width*colours; - unsigned char *s_ptr = buffer; + unsigned int line_bytes = new_width*colours; + unsigned char *s_ptr = buffer; - if ( colours == ZM_COLOUR_GRAY8 ) - { - unsigned char *d_ptr; - for ( unsigned int i = new_width; i > 0; i-- ) - { - d_ptr = rotate_buffer+(i-1); - for ( unsigned int j = new_height; j > 0; j-- ) - { - *d_ptr = *s_ptr++; - d_ptr += line_bytes; - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - Rgb* s_rptr = (Rgb*)s_ptr; - Rgb* d_rptr; - for ( unsigned int i = new_width; i > 0; i-- ) - { - d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2)); - for ( unsigned int j = new_height; j > 0; j-- ) - { - *d_rptr = *s_rptr++; - d_rptr += new_width; - } - } - } - else /* Assume RGB24 */ - { - unsigned char *d_ptr; - for ( unsigned int i = new_width; i > 0; i-- ) - { - d_ptr = rotate_buffer+((i-1)*3); - for ( unsigned int j = new_height; j > 0; j-- ) - { - *d_ptr = *s_ptr++; - *(d_ptr+1) = *s_ptr++; - *(d_ptr+2) = *s_ptr++; - d_ptr += line_bytes; - } - } - } - break; - } - case 180 : - { - unsigned char *s_ptr = buffer+size; - unsigned char *d_ptr = rotate_buffer; + if ( colours == ZM_COLOUR_GRAY8 ) + { + unsigned char *d_ptr; + for ( unsigned int i = new_width; i > 0; i-- ) + { + d_ptr = rotate_buffer+(i-1); + for ( unsigned int j = new_height; j > 0; j-- ) + { + *d_ptr = *s_ptr++; + d_ptr += line_bytes; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr; + for ( unsigned int i = new_width; i > 0; i-- ) + { + d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2)); + for ( unsigned int j = new_height; j > 0; j-- ) + { + *d_rptr = *s_rptr++; + d_rptr += new_width; + } + } + } + else /* Assume RGB24 */ + { + unsigned char *d_ptr; + for ( unsigned int i = new_width; i > 0; i-- ) + { + d_ptr = rotate_buffer+((i-1)*3); + for ( unsigned int j = new_height; j > 0; j-- ) + { + *d_ptr = *s_ptr++; + *(d_ptr+1) = *s_ptr++; + *(d_ptr+2) = *s_ptr++; + d_ptr += line_bytes; + } + } + } + break; + } + case 180 : + { + unsigned char *s_ptr = buffer+size; + unsigned char *d_ptr = rotate_buffer; - if ( colours == ZM_COLOUR_GRAY8 ) - { - while( s_ptr > buffer ) - { - s_ptr--; - *d_ptr++ = *s_ptr; - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - Rgb* s_rptr = (Rgb*)s_ptr; - Rgb* d_rptr = (Rgb*)d_ptr; - while( s_rptr > (Rgb*)buffer ) - { - s_rptr--; - *d_rptr++ = *s_rptr; - } - } - else /* Assume RGB24 */ - { - while( s_ptr > buffer ) - { - s_ptr -= 3; - *d_ptr++ = *s_ptr; - *d_ptr++ = *(s_ptr+1); - *d_ptr++ = *(s_ptr+2); - } - } - break; - } - case 270 : - { - new_height = width; - new_width = height; + if ( colours == ZM_COLOUR_GRAY8 ) + { + while( s_ptr > buffer ) + { + s_ptr--; + *d_ptr++ = *s_ptr; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr = (Rgb*)d_ptr; + while( s_rptr > (Rgb*)buffer ) + { + s_rptr--; + *d_rptr++ = *s_rptr; + } + } + else /* Assume RGB24 */ + { + while( s_ptr > buffer ) + { + s_ptr -= 3; + *d_ptr++ = *s_ptr; + *d_ptr++ = *(s_ptr+1); + *d_ptr++ = *(s_ptr+2); + } + } + break; + } + case 270 : + { + new_height = width; + new_width = height; - unsigned int line_bytes = new_width*colours; - unsigned char *s_ptr = buffer+size; + unsigned int line_bytes = new_width*colours; + unsigned char *s_ptr = buffer+size; - if ( colours == ZM_COLOUR_GRAY8 ) - { - unsigned char *d_ptr; - for ( unsigned int i = new_width; i > 0; i-- ) - { - d_ptr = rotate_buffer+(i-1); - for ( unsigned int j = new_height; j > 0; j-- ) - { - s_ptr--; - *d_ptr = *s_ptr; - d_ptr += line_bytes; - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - Rgb* s_rptr = (Rgb*)s_ptr; - Rgb* d_rptr; - for ( unsigned int i = new_width; i > 0; i-- ) - { - d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2)); - for ( unsigned int j = new_height; j > 0; j-- ) - { - s_rptr--; - *d_rptr = *s_rptr; - d_rptr += new_width; - } - } - } - else /* Assume RGB24 */ - { - unsigned char *d_ptr; - for ( unsigned int i = new_width; i > 0; i-- ) - { - d_ptr = rotate_buffer+((i-1)*3); - for ( unsigned int j = new_height; j > 0; j-- ) - { - *(d_ptr+2) = *(--s_ptr); - *(d_ptr+1) = *(--s_ptr); - *d_ptr = *(--s_ptr); - d_ptr += line_bytes; - } - } - } - break; - } - } + if ( colours == ZM_COLOUR_GRAY8 ) + { + unsigned char *d_ptr; + for ( unsigned int i = new_width; i > 0; i-- ) + { + d_ptr = rotate_buffer+(i-1); + for ( unsigned int j = new_height; j > 0; j-- ) + { + s_ptr--; + *d_ptr = *s_ptr; + d_ptr += line_bytes; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr; + for ( unsigned int i = new_width; i > 0; i-- ) + { + d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2)); + for ( unsigned int j = new_height; j > 0; j-- ) + { + s_rptr--; + *d_rptr = *s_rptr; + d_rptr += new_width; + } + } + } + else /* Assume RGB24 */ + { + unsigned char *d_ptr; + for ( unsigned int i = new_width; i > 0; i-- ) + { + d_ptr = rotate_buffer+((i-1)*3); + for ( unsigned int j = new_height; j > 0; j-- ) + { + *(d_ptr+2) = *(--s_ptr); + *(d_ptr+1) = *(--s_ptr); + *d_ptr = *(--s_ptr); + d_ptr += line_bytes; + } + } + } + break; + } + } - AssignDirect( new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM); - + AssignDirect( new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM); + } /* RGB32 compatible: complete */ void Image::Flip( bool leftright ) { - uint8_t* flip_buffer = AllocBuffer(size); - - unsigned int line_bytes = width*colours; - unsigned int line_bytes2 = 2*line_bytes; - if ( leftright ) - { - // Horizontal flip, left to right - unsigned char *s_ptr = buffer+line_bytes; - unsigned char *d_ptr = flip_buffer; - unsigned char *max_d_ptr = flip_buffer + size; + uint8_t* flip_buffer = AllocBuffer(size); + + unsigned int line_bytes = width*colours; + unsigned int line_bytes2 = 2*line_bytes; + if ( leftright ) + { + // Horizontal flip, left to right + unsigned char *s_ptr = buffer+line_bytes; + unsigned char *d_ptr = flip_buffer; + unsigned char *max_d_ptr = flip_buffer + size; - if ( colours == ZM_COLOUR_GRAY8 ) - { - while( d_ptr < max_d_ptr ) - { - for ( unsigned int j = 0; j < width; j++ ) - { - s_ptr--; - *d_ptr++ = *s_ptr; - } - s_ptr += line_bytes2; - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - Rgb* s_rptr = (Rgb*)s_ptr; - Rgb* d_rptr = (Rgb*)flip_buffer; - Rgb* max_d_rptr = (Rgb*)max_d_ptr; - while( d_rptr < max_d_rptr ) - { - for ( unsigned int j = 0; j < width; j++ ) - { - s_rptr--; - *d_rptr++ = *s_rptr; - } - s_rptr += width * 2; - } - } - else /* Assume RGB24 */ - { - while( d_ptr < max_d_ptr ) - { - for ( unsigned int j = 0; j < width; j++ ) - { - s_ptr -= 3; - *d_ptr++ = *s_ptr; - *d_ptr++ = *(s_ptr+1); - *d_ptr++ = *(s_ptr+2); - } - s_ptr += line_bytes2; - } - } - } - else - { - // Vertical flip, top to bottom - unsigned char *s_ptr = buffer+(height*line_bytes); - unsigned char *d_ptr = flip_buffer; + if ( colours == ZM_COLOUR_GRAY8 ) + { + while( d_ptr < max_d_ptr ) + { + for ( unsigned int j = 0; j < width; j++ ) + { + s_ptr--; + *d_ptr++ = *s_ptr; + } + s_ptr += line_bytes2; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr = (Rgb*)flip_buffer; + Rgb* max_d_rptr = (Rgb*)max_d_ptr; + while( d_rptr < max_d_rptr ) + { + for ( unsigned int j = 0; j < width; j++ ) + { + s_rptr--; + *d_rptr++ = *s_rptr; + } + s_rptr += width * 2; + } + } + else /* Assume RGB24 */ + { + while( d_ptr < max_d_ptr ) + { + for ( unsigned int j = 0; j < width; j++ ) + { + s_ptr -= 3; + *d_ptr++ = *s_ptr; + *d_ptr++ = *(s_ptr+1); + *d_ptr++ = *(s_ptr+2); + } + s_ptr += line_bytes2; + } + } + } + else + { + // Vertical flip, top to bottom + unsigned char *s_ptr = buffer+(height*line_bytes); + unsigned char *d_ptr = flip_buffer; - while( s_ptr > buffer ) - { - s_ptr -= line_bytes; - memcpy( d_ptr, s_ptr, line_bytes ); - d_ptr += line_bytes; - } - } - - AssignDirect( width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM); - + while( s_ptr > buffer ) + { + s_ptr -= line_bytes; + memcpy( d_ptr, s_ptr, line_bytes ); + d_ptr += line_bytes; + } + } + + AssignDirect( width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM); + } void Image::Scale( unsigned int factor ) { - if ( !factor ) - { - Error( "Bogus scale factor %d found", factor ); - return; - } - if ( factor == ZM_SCALE_BASE ) - { - return; - } + if ( !factor ) + { + Error( "Bogus scale factor %d found", factor ); + return; + } + if ( factor == ZM_SCALE_BASE ) + { + return; + } - unsigned int new_width = (width*factor)/ZM_SCALE_BASE; - unsigned int new_height = (height*factor)/ZM_SCALE_BASE; - - size_t scale_buffer_size = (new_width+1) * (new_height+1) * colours; - - uint8_t* scale_buffer = AllocBuffer(scale_buffer_size); - - if ( factor > ZM_SCALE_BASE ) - { - unsigned char *pd = scale_buffer; - unsigned int wc = width*colours; - unsigned int nwc = new_width*colours; - unsigned int h_count = ZM_SCALE_BASE/2; - unsigned int last_h_index = 0; - unsigned int last_w_index = 0; - unsigned int h_index; - for ( unsigned int y = 0; y < height; y++ ) - { - unsigned char *ps = &buffer[y*wc]; - unsigned int w_count = ZM_SCALE_BASE/2; - unsigned int w_index; - last_w_index = 0; - for ( unsigned int x = 0; x < width; x++ ) - { - w_count += factor; - w_index = w_count/ZM_SCALE_BASE; - for (unsigned int f = last_w_index; f < w_index; f++ ) - { - for ( unsigned int c = 0; c < colours; c++ ) - { - *pd++ = *(ps+c); - } - } - ps += colours; - last_w_index = w_index; - } - h_count += factor; - h_index = h_count/ZM_SCALE_BASE; - for ( unsigned int f = last_h_index+1; f < h_index; f++ ) - { - memcpy( pd, pd-nwc, nwc ); - pd += nwc; - } - last_h_index = h_index; - } - new_width = last_w_index; - new_height = last_h_index; - } - else - { - unsigned char *pd = scale_buffer; - unsigned int wc = width*colours; - unsigned int xstart = factor/2; - unsigned int ystart = factor/2; - unsigned int h_count = ystart; - unsigned int last_h_index = 0; - unsigned int last_w_index = 0; - unsigned int h_index; - for ( unsigned int y = 0; y < (unsigned int)height; y++ ) - { - h_count += factor; - h_index = h_count/ZM_SCALE_BASE; - if ( h_index > last_h_index ) - { - unsigned int w_count = xstart; - unsigned int w_index; - last_w_index = 0; + unsigned int new_width = (width*factor)/ZM_SCALE_BASE; + unsigned int new_height = (height*factor)/ZM_SCALE_BASE; + + size_t scale_buffer_size = (new_width+1) * (new_height+1) * colours; + + uint8_t* scale_buffer = AllocBuffer(scale_buffer_size); + + if ( factor > ZM_SCALE_BASE ) + { + unsigned char *pd = scale_buffer; + unsigned int wc = width*colours; + unsigned int nwc = new_width*colours; + unsigned int h_count = ZM_SCALE_BASE/2; + unsigned int last_h_index = 0; + unsigned int last_w_index = 0; + unsigned int h_index; + for ( unsigned int y = 0; y < height; y++ ) + { + unsigned char *ps = &buffer[y*wc]; + unsigned int w_count = ZM_SCALE_BASE/2; + unsigned int w_index; + last_w_index = 0; + for ( unsigned int x = 0; x < width; x++ ) + { + w_count += factor; + w_index = w_count/ZM_SCALE_BASE; + for (unsigned int f = last_w_index; f < w_index; f++ ) + { + for ( unsigned int c = 0; c < colours; c++ ) + { + *pd++ = *(ps+c); + } + } + ps += colours; + last_w_index = w_index; + } + h_count += factor; + h_index = h_count/ZM_SCALE_BASE; + for ( unsigned int f = last_h_index+1; f < h_index; f++ ) + { + memcpy( pd, pd-nwc, nwc ); + pd += nwc; + } + last_h_index = h_index; + } + new_width = last_w_index; + new_height = last_h_index; + } + else + { + unsigned char *pd = scale_buffer; + unsigned int wc = width*colours; + unsigned int xstart = factor/2; + unsigned int ystart = factor/2; + unsigned int h_count = ystart; + unsigned int last_h_index = 0; + unsigned int last_w_index = 0; + unsigned int h_index; + for ( unsigned int y = 0; y < (unsigned int)height; y++ ) + { + h_count += factor; + h_index = h_count/ZM_SCALE_BASE; + if ( h_index > last_h_index ) + { + unsigned int w_count = xstart; + unsigned int w_index; + last_w_index = 0; - unsigned char *ps = &buffer[y*wc]; - for ( unsigned int x = 0; x < (unsigned int)width; x++ ) - { - w_count += factor; - w_index = w_count/ZM_SCALE_BASE; - - if ( w_index > last_w_index ) - { - for ( unsigned int c = 0; c < colours; c++ ) - { - *pd++ = *ps++; - } - } - else - { - ps += colours; - } - last_w_index = w_index; - } - } - last_h_index = h_index; - } - new_width = last_w_index; - new_height = last_h_index; - } - - AssignDirect( new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM); - + unsigned char *ps = &buffer[y*wc]; + for ( unsigned int x = 0; x < (unsigned int)width; x++ ) + { + w_count += factor; + w_index = w_count/ZM_SCALE_BASE; + + if ( w_index > last_w_index ) + { + for ( unsigned int c = 0; c < colours; c++ ) + { + *pd++ = *ps++; + } + } + else + { + ps += colours; + } + last_w_index = w_index; + } + } + last_h_index = h_index; + } + new_width = last_w_index; + new_height = last_h_index; + } + + AssignDirect( new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM); + } void Image::Deinterlace_Discard() { - /* Simple deinterlacing. Copy the even lines into the odd lines */ - - if ( colours == ZM_COLOUR_GRAY8 ) - { - const uint8_t *psrc; - uint8_t *pdest; - for (unsigned int y = 0; y < (unsigned int)height; y += 2) - { - psrc = buffer + (y * width); - pdest = buffer + ((y+1) * width); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pdest++ = *psrc++; - } - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - const uint8_t *psrc; - uint8_t *pdest; - for (unsigned int y = 0; y < (unsigned int)height; y += 2) - { - psrc = buffer + ((y * width) * 3); - pdest = buffer + (((y+1) * width) * 3); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pdest++ = *psrc++; - *pdest++ = *psrc++; - *pdest++ = *psrc++; - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - const Rgb *psrc; - Rgb *pdest; - for (unsigned int y = 0; y < (unsigned int)height; y += 2) - { - psrc = (Rgb*)(buffer + ((y * width) << 2)); - pdest = (Rgb*)(buffer + (((y+1) * width) << 2)); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pdest++ = *psrc++; - } - } - } else { - Error("Deinterlace called with unexpected colours: %d", colours); - } - + /* Simple deinterlacing. Copy the even lines into the odd lines */ + + if ( colours == ZM_COLOUR_GRAY8 ) + { + const uint8_t *psrc; + uint8_t *pdest; + for (unsigned int y = 0; y < (unsigned int)height; y += 2) + { + psrc = buffer + (y * width); + pdest = buffer + ((y+1) * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + const uint8_t *psrc; + uint8_t *pdest; + for (unsigned int y = 0; y < (unsigned int)height; y += 2) + { + psrc = buffer + ((y * width) * 3); + pdest = buffer + (((y+1) * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pdest++ = *psrc++; + *pdest++ = *psrc++; + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + const Rgb *psrc; + Rgb *pdest; + for (unsigned int y = 0; y < (unsigned int)height; y += 2) + { + psrc = (Rgb*)(buffer + ((y * width) << 2)); + pdest = (Rgb*)(buffer + (((y+1) * width) << 2)); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pdest++ = *psrc++; + } + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + } void Image::Deinterlace_Linear() { - /* Simple deinterlacing. The odd lines are average of the line above and line below */ - - const uint8_t *pbelow, *pabove; - uint8_t *pcurrent; - - if ( colours == ZM_COLOUR_GRAY8 ) - { - for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) - { - pabove = buffer + ((y-1) * width); - pbelow = buffer + ((y+1) * width); - pcurrent = buffer + (y * width); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - } - } - /* Special case for the last line */ - pcurrent = buffer + ((height-1) * width); - pabove = buffer + ((height-2) * width); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pcurrent++ = *pabove++; - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) - { - pabove = buffer + (((y-1) * width) * 3); - pbelow = buffer + (((y+1) * width) * 3); - pcurrent = buffer + ((y * width) * 3); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - } - } - /* Special case for the last line */ - pcurrent = buffer + (((height-1) * width) * 3); - pabove = buffer + (((height-2) * width) * 3); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pcurrent++ = *pabove++; - *pcurrent++ = *pabove++; - *pcurrent++ = *pabove++; - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) - { - pabove = buffer + (((y-1) * width) << 2); - pbelow = buffer + (((y+1) * width) << 2); - pcurrent = buffer + ((y * width) << 2); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - *pcurrent++ = (*pabove++ + *pbelow++) >> 1; - } - } - /* Special case for the last line */ - pcurrent = buffer + (((height-1) * width) << 2); - pabove = buffer + (((height-2) * width) << 2); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pcurrent++ = *pabove++; - *pcurrent++ = *pabove++; - *pcurrent++ = *pabove++; - *pcurrent++ = *pabove++; - } - } else { - Error("Deinterlace called with unexpected colours: %d", colours); - } - + /* Simple deinterlacing. The odd lines are average of the line above and line below */ + + const uint8_t *pbelow, *pabove; + uint8_t *pcurrent; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) + { + pabove = buffer + ((y-1) * width); + pbelow = buffer + ((y+1) * width); + pcurrent = buffer + (y * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + } + } + /* Special case for the last line */ + pcurrent = buffer + ((height-1) * width); + pabove = buffer + ((height-2) * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = *pabove++; + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) + { + pabove = buffer + (((y-1) * width) * 3); + pbelow = buffer + (((y+1) * width) * 3); + pcurrent = buffer + ((y * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + } + } + /* Special case for the last line */ + pcurrent = buffer + (((height-1) * width) * 3); + pabove = buffer + (((height-2) * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) + { + pabove = buffer + (((y-1) * width) << 2); + pbelow = buffer + (((y+1) * width) << 2); + pcurrent = buffer + ((y * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + } + } + /* Special case for the last line */ + pcurrent = buffer + (((height-1) * width) << 2); + pabove = buffer + (((height-2) * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + } void Image::Deinterlace_Blend() { - /* Simple deinterlacing. Blend the fields together. 50% blend */ - - uint8_t *pabove, *pcurrent; - - if ( colours == ZM_COLOUR_GRAY8 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { - pabove = buffer + ((y-1) * width); - pcurrent = buffer + (y * width); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - } - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { - pabove = buffer + (((y-1) * width) * 3); - pcurrent = buffer + ((y * width) * 3); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { - pabove = buffer + (((y-1) * width) << 2); - pcurrent = buffer + ((y * width) << 2); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - *pabove = (*pabove + *pcurrent) >> 1; - *pcurrent++ = *pabove++; - } - } - } else { - Error("Deinterlace called with unexpected colours: %d", colours); - } - + /* Simple deinterlacing. Blend the fields together. 50% blend */ + + uint8_t *pabove, *pcurrent; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + ((y-1) * width); + pcurrent = buffer + (y * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) * 3); + pcurrent = buffer + ((y * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) << 2); + pcurrent = buffer + ((y * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + } + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + } void Image::Deinterlace_Blend_CustomRatio(int divider) { - /* Simple deinterlacing. Blend the fields together at a custom ratio. */ - /* 1 = 50% blending */ - /* 2 = 25% blending */ - /* 3 = 12.% blending */ - /* 4 = 6.25% blending */ - - uint8_t *pabove, *pcurrent; - uint8_t subpix1, subpix2; - - if ( divider < 1 || divider > 4 ) { - Error("Deinterlace called with invalid blend ratio"); - } - - if ( colours == ZM_COLOUR_GRAY8 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { - pabove = buffer + ((y-1) * width); - pcurrent = buffer + (y * width); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - } - } - } - else if ( colours == ZM_COLOUR_RGB24 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { - pabove = buffer + (((y-1) * width) * 3); - pcurrent = buffer + ((y * width) * 3); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - } - } - } - else if ( colours == ZM_COLOUR_RGB32 ) - { - for (unsigned int y = 1; y < (unsigned int)height; y += 2) - { - pabove = buffer + (((y-1) * width) << 2); - pcurrent = buffer + ((y * width) << 2); - for (unsigned int x = 0; x < (unsigned int)width; x++) { - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; - subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; - *pcurrent++ = subpix1; - *pabove++ = subpix2; - } - } - } else { - Error("Deinterlace called with unexpected colours: %d", colours); - } - + /* Simple deinterlacing. Blend the fields together at a custom ratio. */ + /* 1 = 50% blending */ + /* 2 = 25% blending */ + /* 3 = 12.% blending */ + /* 4 = 6.25% blending */ + + uint8_t *pabove, *pcurrent; + uint8_t subpix1, subpix2; + + if ( divider < 1 || divider > 4 ) { + Error("Deinterlace called with invalid blend ratio"); + } + + if ( colours == ZM_COLOUR_GRAY8 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + ((y-1) * width); + pcurrent = buffer + (y * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) * 3); + pcurrent = buffer + ((y * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) << 2); + pcurrent = buffer + ((y * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + } + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + } void Image::Deinterlace_4Field(const Image* next_image, unsigned int threshold) { - if ( !(width == next_image->width && height == next_image->height && colours == next_image->colours && subpixelorder == next_image->subpixelorder) ) - { - Panic( "Attempt to deinterlace different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, next_image->width, next_image->height, next_image->colours, next_image->subpixelorder); - } - - switch(colours) { - case ZM_COLOUR_RGB24: - { - if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { - /* BGR subpixel order */ - std_deinterlace_4field_bgr(buffer, next_image->buffer, threshold, width, height); - } else { - /* Assume RGB subpixel order */ - std_deinterlace_4field_rgb(buffer, next_image->buffer, threshold, width, height); - } - break; - } - case ZM_COLOUR_RGB32: - { - if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - /* ARGB subpixel order */ - (*fptr_deinterlace_4field_argb)(buffer, next_image->buffer, threshold, width, height); - } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - /* ABGR subpixel order */ - (*fptr_deinterlace_4field_abgr)(buffer, next_image->buffer, threshold, width, height); - } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* BGRA subpixel order */ - (*fptr_deinterlace_4field_bgra)(buffer, next_image->buffer, threshold, width, height); - } else { - /* Assume RGBA subpixel order */ - (*fptr_deinterlace_4field_rgba)(buffer, next_image->buffer, threshold, width, height); - } - break; - } - case ZM_COLOUR_GRAY8: - (*fptr_deinterlace_4field_gray8)(buffer, next_image->buffer, threshold, width, height); - break; - default: - Panic("Deinterlace_4Field called with unexpected colours: %d",colours); - break; - } - + if ( !(width == next_image->width && height == next_image->height && colours == next_image->colours && subpixelorder == next_image->subpixelorder) ) + { + Panic( "Attempt to deinterlace different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, next_image->width, next_image->height, next_image->colours, next_image->subpixelorder); + } + + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + std_deinterlace_4field_bgr(buffer, next_image->buffer, threshold, width, height); + } else { + /* Assume RGB subpixel order */ + std_deinterlace_4field_rgb(buffer, next_image->buffer, threshold, width, height); + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + (*fptr_deinterlace_4field_argb)(buffer, next_image->buffer, threshold, width, height); + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + (*fptr_deinterlace_4field_abgr)(buffer, next_image->buffer, threshold, width, height); + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + (*fptr_deinterlace_4field_bgra)(buffer, next_image->buffer, threshold, width, height); + } else { + /* Assume RGBA subpixel order */ + (*fptr_deinterlace_4field_rgba)(buffer, next_image->buffer, threshold, width, height); + } + break; + } + case ZM_COLOUR_GRAY8: + (*fptr_deinterlace_4field_gray8)(buffer, next_image->buffer, threshold, width, height); + break; + default: + Panic("Deinterlace_4Field called with unexpected colours: %d",colours); + break; + } + } @@ -3124,343 +3124,343 @@ __attribute__((noinline,__target__("sse2"))) #endif void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - static uint32_t divider = 0; - static uint32_t clearmask = 0; - static double current_blendpercent = 0.0; - - if(current_blendpercent != blendpercent) { - /* Attempt to match the blending percent to one of the possible values */ - if(blendpercent < 2.34375) { - // 1.5625% blending - divider = 6; - clearmask = 0x03030303; - } else if(blendpercent < 4.6875) { - // 3.125% blending - divider = 5; - clearmask = 0x07070707; - } else if(blendpercent < 9.375) { - // 6.25% blending - divider = 4; - clearmask = 0x0F0F0F0F; - } else if(blendpercent < 18.75) { - // 12.5% blending - divider = 3; - clearmask = 0x1F1F1F1F; - } else if(blendpercent < 37.5) { - // 25% blending - divider = 2; - clearmask = 0x3F3F3F3F; - } else { - // 50% blending - divider = 1; - clearmask = 0x7F7F7F7F; - } - current_blendpercent = blendpercent; - } + static uint32_t divider = 0; + static uint32_t clearmask = 0; + static double current_blendpercent = 0.0; + + if(current_blendpercent != blendpercent) { + /* Attempt to match the blending percent to one of the possible values */ + if(blendpercent < 2.34375) { + // 1.5625% blending + divider = 6; + clearmask = 0x03030303; + } else if(blendpercent < 4.6875) { + // 3.125% blending + divider = 5; + clearmask = 0x07070707; + } else if(blendpercent < 9.375) { + // 6.25% blending + divider = 4; + clearmask = 0x0F0F0F0F; + } else if(blendpercent < 18.75) { + // 12.5% blending + divider = 3; + clearmask = 0x1F1F1F1F; + } else if(blendpercent < 37.5) { + // 25% blending + divider = 2; + clearmask = 0x3F3F3F3F; + } else { + // 50% blending + divider = 1; + clearmask = 0x7F7F7F7F; + } + current_blendpercent = blendpercent; + } - __asm__ __volatile__( - "movd %4, %%xmm3\n\t" - "movd %5, %%xmm4\n\t" - "pshufd $0x0, %%xmm3, %%xmm3\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x10, %2\n\t" - "sse2_fastblend_iter:\n\t" - "movdqa (%0,%3),%%xmm0\n\t" - "movdqa %%xmm0,%%xmm2\n\t" - "movdqa (%1,%3),%%xmm1\n\t" - "psrlq %%xmm4,%%xmm0\n\t" - "psrlq %%xmm4,%%xmm1\n\t" - "pand %%xmm3,%%xmm1\n\t" - "pand %%xmm3,%%xmm0\n\t" - "psubb %%xmm0,%%xmm1\n\t" - "paddb %%xmm2,%%xmm1\n\t" - "movntdq %%xmm1,(%2,%3)\n\t" - "sub $0x10, %3\n\t" - "jnz sse2_fastblend_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (clearmask), "m" (divider) - : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "cc", "memory" - ); + __asm__ __volatile__( + "movd %4, %%xmm3\n\t" + "movd %5, %%xmm4\n\t" + "pshufd $0x0, %%xmm3, %%xmm3\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x10, %2\n\t" + "sse2_fastblend_iter:\n\t" + "movdqa (%0,%3),%%xmm0\n\t" + "movdqa %%xmm0,%%xmm2\n\t" + "movdqa (%1,%3),%%xmm1\n\t" + "psrlq %%xmm4,%%xmm0\n\t" + "psrlq %%xmm4,%%xmm1\n\t" + "pand %%xmm3,%%xmm1\n\t" + "pand %%xmm3,%%xmm0\n\t" + "psubb %%xmm0,%%xmm1\n\t" + "paddb %%xmm2,%%xmm1\n\t" + "movntdq %%xmm1,(%2,%3)\n\t" + "sub $0x10, %3\n\t" + "jnz sse2_fastblend_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (clearmask), "m" (divider) + : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } __attribute__((noinline)) void std_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { - static int divider = 0; - static double current_blendpercent = 0.0; - const uint8_t* const max_ptr = result + count; - - if(current_blendpercent != blendpercent) { - /* Attempt to match the blending percent to one of the possible values */ - if(blendpercent < 2.34375) { - // 1.5625% blending - divider = 6; - } else if(blendpercent < 4.6875) { - // 3.125% blending - divider = 5; - } else if(blendpercent < 9.375) { - // 6.25% blending - divider = 4; - } else if(blendpercent < 18.75) { - // 12.5% blending - divider = 3; - } else if(blendpercent < 37.5) { - // 25% blending - divider = 2; - } else { - // 50% blending - divider = 1; - } - current_blendpercent = blendpercent; - } - + static int divider = 0; + static double current_blendpercent = 0.0; + const uint8_t* const max_ptr = result + count; + + if(current_blendpercent != blendpercent) { + /* Attempt to match the blending percent to one of the possible values */ + if(blendpercent < 2.34375) { + // 1.5625% blending + divider = 6; + } else if(blendpercent < 4.6875) { + // 3.125% blending + divider = 5; + } else if(blendpercent < 9.375) { + // 6.25% blending + divider = 4; + } else if(blendpercent < 18.75) { + // 12.5% blending + divider = 3; + } else if(blendpercent < 37.5) { + // 25% blending + divider = 2; + } else { + // 50% blending + divider = 1; + } + current_blendpercent = blendpercent; + } + - while(result < max_ptr) { - result[0] = ((col2[0] - col1[0])>>divider) + col1[0]; - result[1] = ((col2[1] - col1[1])>>divider) + col1[1]; - result[2] = ((col2[2] - col1[2])>>divider) + col1[2]; - result[3] = ((col2[3] - col1[3])>>divider) + col1[3]; - result[4] = ((col2[4] - col1[4])>>divider) + col1[4]; - result[5] = ((col2[5] - col1[5])>>divider) + col1[5]; - result[6] = ((col2[6] - col1[6])>>divider) + col1[6]; - result[7] = ((col2[7] - col1[7])>>divider) + col1[7]; - result[8] = ((col2[8] - col1[8])>>divider) + col1[8]; - result[9] = ((col2[9] - col1[9])>>divider) + col1[9]; - result[10] = ((col2[10] - col1[10])>>divider) + col1[10]; - result[11] = ((col2[11] - col1[11])>>divider) + col1[11]; - result[12] = ((col2[12] - col1[12])>>divider) + col1[12]; - result[13] = ((col2[13] - col1[13])>>divider) + col1[13]; - result[14] = ((col2[14] - col1[14])>>divider) + col1[14]; - result[15] = ((col2[15] - col1[15])>>divider) + col1[15]; - - col1 += 16; - col2 += 16; - result += 16; - } + while(result < max_ptr) { + result[0] = ((col2[0] - col1[0])>>divider) + col1[0]; + result[1] = ((col2[1] - col1[1])>>divider) + col1[1]; + result[2] = ((col2[2] - col1[2])>>divider) + col1[2]; + result[3] = ((col2[3] - col1[3])>>divider) + col1[3]; + result[4] = ((col2[4] - col1[4])>>divider) + col1[4]; + result[5] = ((col2[5] - col1[5])>>divider) + col1[5]; + result[6] = ((col2[6] - col1[6])>>divider) + col1[6]; + result[7] = ((col2[7] - col1[7])>>divider) + col1[7]; + result[8] = ((col2[8] - col1[8])>>divider) + col1[8]; + result[9] = ((col2[9] - col1[9])>>divider) + col1[9]; + result[10] = ((col2[10] - col1[10])>>divider) + col1[10]; + result[11] = ((col2[11] - col1[11])>>divider) + col1[11]; + result[12] = ((col2[12] - col1[12])>>divider) + col1[12]; + result[13] = ((col2[13] - col1[13])>>divider) + col1[13]; + result[14] = ((col2[14] - col1[14])>>divider) + col1[14]; + result[15] = ((col2[15] - col1[15])>>divider) + col1[15]; + + col1 += 16; + col2 += 16; + result += 16; + } } __attribute__((noinline)) void std_blend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { - double divide = blendpercent / 100.0; - double opacity = 1.0 - divide; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - *result++ = (*col1++ * opacity) + (*col2++ * divide); - - } + double divide = blendpercent / 100.0; + double opacity = 1.0 - divide; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + *result++ = (*col1++ * opacity) + (*col2++ * divide); + + } } /************************************************* DELTA FUNCTIONS *************************************************/ /* Grayscale */ __attribute__((noinline)) void std_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 16 bytes (16 grayscale pixels) at a time */ - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - result[0] = abs(col1[0] - col2[0]); - result[1] = abs(col1[1] - col2[1]); - result[2] = abs(col1[2] - col2[2]); - result[3] = abs(col1[3] - col2[3]); - result[4] = abs(col1[4] - col2[4]); - result[5] = abs(col1[5] - col2[5]); - result[6] = abs(col1[6] - col2[6]); - result[7] = abs(col1[7] - col2[7]); - result[8] = abs(col1[8] - col2[8]); - result[9] = abs(col1[9] - col2[9]); - result[10] = abs(col1[10] - col2[10]); - result[11] = abs(col1[11] - col2[11]); - result[12] = abs(col1[12] - col2[12]); - result[13] = abs(col1[13] - col2[13]); - result[14] = abs(col1[14] - col2[14]); - result[15] = abs(col1[15] - col2[15]); - - col1 += 16; - col2 += 16; - result += 16; - } + /* Loop unrolling is used to work on 16 bytes (16 grayscale pixels) at a time */ + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + result[0] = abs(col1[0] - col2[0]); + result[1] = abs(col1[1] - col2[1]); + result[2] = abs(col1[2] - col2[2]); + result[3] = abs(col1[3] - col2[3]); + result[4] = abs(col1[4] - col2[4]); + result[5] = abs(col1[5] - col2[5]); + result[6] = abs(col1[6] - col2[6]); + result[7] = abs(col1[7] - col2[7]); + result[8] = abs(col1[8] - col2[8]); + result[9] = abs(col1[9] - col2[9]); + result[10] = abs(col1[10] - col2[10]); + result[11] = abs(col1[11] - col2[11]); + result[12] = abs(col1[12] - col2[12]); + result[13] = abs(col1[13] - col2[13]); + result[14] = abs(col1[14] - col2[14]); + result[15] = abs(col1[15] - col2[15]); + + col1 += 16; + col2 += 16; + result += 16; + } } /* RGB24: RGB */ __attribute__((noinline)) void std_delta8_rgb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ - int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - r = abs(col1[0] - col2[0]); - g = abs(col1[1] - col2[1]); - b = abs(col1[2] - col2[2]); - result[0] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[3] - col2[3]); - g = abs(col1[4] - col2[4]); - b = abs(col1[5] - col2[5]); - result[1] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[6] - col2[6]); - g = abs(col1[7] - col2[7]); - b = abs(col1[8] - col2[8]); - result[2] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[9] - col2[9]); - g = abs(col1[10] - col2[10]); - b = abs(col1[11] - col2[11]); - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 12; - col2 += 12; - result += 4; - } + /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + b = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[3] - col2[3]); + g = abs(col1[4] - col2[4]); + b = abs(col1[5] - col2[5]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[6] - col2[6]); + g = abs(col1[7] - col2[7]); + b = abs(col1[8] - col2[8]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + b = abs(col1[11] - col2[11]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + col2 += 12; + result += 4; + } } /* RGB24: BGR */ __attribute__((noinline)) void std_delta8_bgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ - int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - b = abs(col1[0] - col2[0]); - g = abs(col1[1] - col2[1]); - r = abs(col1[2] - col2[2]); - result[0] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[3] - col2[3]); - g = abs(col1[4] - col2[4]); - r = abs(col1[5] - col2[5]); - result[1] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[6] - col2[6]); - g = abs(col1[7] - col2[7]); - r = abs(col1[8] - col2[8]); - result[2] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[9] - col2[9]); - g = abs(col1[10] - col2[10]); - r = abs(col1[11] - col2[11]); - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 12; - col2 += 12; - result += 4; - } + /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + r = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[3] - col2[3]); + g = abs(col1[4] - col2[4]); + r = abs(col1[5] - col2[5]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[6] - col2[6]); + g = abs(col1[7] - col2[7]); + r = abs(col1[8] - col2[8]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + r = abs(col1[11] - col2[11]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + col2 += 12; + result += 4; + } } /* RGB32: RGBA */ __attribute__((noinline)) void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - r = abs(col1[0] - col2[0]); - g = abs(col1[1] - col2[1]); - b = abs(col1[2] - col2[2]); - result[0] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[4] - col2[4]); - g = abs(col1[5] - col2[5]); - b = abs(col1[6] - col2[6]); - result[1] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[8] - col2[8]); - g = abs(col1[9] - col2[9]); - b = abs(col1[10] - col2[10]); - result[2] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[12] - col2[12]); - g = abs(col1[13] - col2[13]); - b = abs(col1[14] - col2[14]); - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - col2 += 16; - result += 4; - } + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + b = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[4] - col2[4]); + g = abs(col1[5] - col2[5]); + b = abs(col1[6] - col2[6]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[8] - col2[8]); + g = abs(col1[9] - col2[9]); + b = abs(col1[10] - col2[10]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[12] - col2[12]); + g = abs(col1[13] - col2[13]); + b = abs(col1[14] - col2[14]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } } /* RGB32: BGRA */ __attribute__((noinline)) void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - b = abs(col1[0] - col2[0]); - g = abs(col1[1] - col2[1]); - r = abs(col1[2] - col2[2]); - result[0] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[4] - col2[4]); - g = abs(col1[5] - col2[5]); - r = abs(col1[6] - col2[6]); - result[1] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[8] - col2[8]); - g = abs(col1[9] - col2[9]); - r = abs(col1[10] - col2[10]); - result[2] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[12] - col2[12]); - g = abs(col1[13] - col2[13]); - r = abs(col1[14] - col2[14]); - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - col2 += 16; - result += 4; - } + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + r = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[4] - col2[4]); + g = abs(col1[5] - col2[5]); + r = abs(col1[6] - col2[6]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[8] - col2[8]); + g = abs(col1[9] - col2[9]); + r = abs(col1[10] - col2[10]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[12] - col2[12]); + g = abs(col1[13] - col2[13]); + r = abs(col1[14] - col2[14]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } } /* RGB32: ARGB */ __attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - r = abs(col1[1] - col2[1]); - g = abs(col1[2] - col2[2]); - b = abs(col1[3] - col2[3]); - result[0] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[5] - col2[5]); - g = abs(col1[6] - col2[6]); - b = abs(col1[7] - col2[7]); - result[1] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[9] - col2[9]); - g = abs(col1[10] - col2[10]); - b = abs(col1[11] - col2[11]); - result[2] = (r + r + b + g + g + g + g + g)>>3; - r = abs(col1[13] - col2[13]); - g = abs(col1[14] - col2[14]); - b = abs(col1[15] - col2[15]); - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - col2 += 16; - result += 4; - } + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = abs(col1[1] - col2[1]); + g = abs(col1[2] - col2[2]); + b = abs(col1[3] - col2[3]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[5] - col2[5]); + g = abs(col1[6] - col2[6]); + b = abs(col1[7] - col2[7]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + b = abs(col1[11] - col2[11]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[13] - col2[13]); + g = abs(col1[14] - col2[14]); + b = abs(col1[15] - col2[15]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } } /* RGB32: ABGR */ __attribute__((noinline)) void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { - /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ - int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - b = abs(col1[1] - col2[1]); - g = abs(col1[2] - col2[2]); - r = abs(col1[3] - col2[3]); - result[0] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[5] - col2[5]); - g = abs(col1[6] - col2[6]); - r = abs(col1[7] - col2[7]); - result[1] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[9] - col2[9]); - g = abs(col1[10] - col2[10]); - r = abs(col1[11] - col2[11]); - result[2] = (r + r + b + g + g + g + g + g)>>3; - b = abs(col1[13] - col2[13]); - g = abs(col1[14] - col2[14]); - r = abs(col1[15] - col2[15]); - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - col2 += 16; - result += 4; - } + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = abs(col1[1] - col2[1]); + g = abs(col1[2] - col2[2]); + r = abs(col1[3] - col2[3]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[5] - col2[5]); + g = abs(col1[6] - col2[6]); + r = abs(col1[7] - col2[7]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + r = abs(col1[11] - col2[11]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[13] - col2[13]); + g = abs(col1[14] - col2[14]); + r = abs(col1[15] - col2[15]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } } /* Grayscale SSE2 */ @@ -3470,27 +3470,27 @@ __attribute__((noinline,__target__("sse2"))) void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __asm__ __volatile__ ( - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x10, %2\n\t" - "sse2_delta8_gray8_iter:\n\t" - "movdqa (%0,%3), %%xmm1\n\t" - "movdqa (%1,%3), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm3\n\t" - "movdqa %%xmm2, %%xmm4\n\t" - "pmaxub %%xmm1, %%xmm2\n\t" - "pminub %%xmm3, %%xmm4\n\t" - "psubb %%xmm4, %%xmm2\n\t" - "movntdq %%xmm2, (%2,%3)\n\t" - "sub $0x10, %3\n\t" - "jnz sse2_delta8_gray8_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count) - : "%xmm1", "%xmm2", "%xmm3", "%xmm4", "cc", "memory" - ); + __asm__ __volatile__ ( + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x10, %2\n\t" + "sse2_delta8_gray8_iter:\n\t" + "movdqa (%0,%3), %%xmm1\n\t" + "movdqa (%1,%3), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm3\n\t" + "movdqa %%xmm2, %%xmm4\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm3, %%xmm4\n\t" + "psubb %%xmm4, %%xmm2\n\t" + "movntdq %%xmm2, (%2,%3)\n\t" + "sub $0x10, %3\n\t" + "jnz sse2_delta8_gray8_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%xmm1", "%xmm2", "%xmm3", "%xmm4", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3501,54 +3501,54 @@ __attribute__((noinline,__target__("sse2"))) void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "sse2_delta8_rgba_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" - "movdqa %%xmm2, %%xmm6\n\t" - "pmaxub %%xmm1, %%xmm2\n\t" - "pminub %%xmm5, %%xmm6\n\t" - "psubb %%xmm6, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm3\n\t" - "psrld $0x8, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm1, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "packssdw %%xmm1, %%xmm1\n\t" - "packuswb %%xmm1, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz sse2_delta8_rgba_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" - ); + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_rgba_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_rgba_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3559,54 +3559,54 @@ __attribute__((noinline,__target__("sse2"))) void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "sse2_delta8_bgra_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" - "movdqa %%xmm2, %%xmm6\n\t" - "pmaxub %%xmm1, %%xmm2\n\t" - "pminub %%xmm5, %%xmm6\n\t" - "psubb %%xmm6, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm3\n\t" - "psrld $0x8, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "packssdw %%xmm1, %%xmm1\n\t" - "packuswb %%xmm1, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz sse2_delta8_bgra_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" - ); + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_bgra_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_bgra_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3617,55 +3617,55 @@ __attribute__((noinline,__target__("sse2"))) void sse2_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "sse2_delta8_argb_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" - "movdqa %%xmm2, %%xmm6\n\t" - "pmaxub %%xmm1, %%xmm2\n\t" - "pminub %%xmm5, %%xmm6\n\t" - "psubb %%xmm6, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm3\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "psrld $0x8, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm1, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x18, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "packssdw %%xmm1, %%xmm1\n\t" - "packuswb %%xmm1, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz sse2_delta8_argb_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" - ); + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_argb_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_argb_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3676,55 +3676,55 @@ __attribute__((noinline,__target__("sse2"))) void sse2_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "sse2_delta8_abgr_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" - "movdqa %%xmm2, %%xmm6\n\t" - "pmaxub %%xmm1, %%xmm2\n\t" - "pminub %%xmm5, %%xmm6\n\t" - "psubb %%xmm6, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm3\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "psrld $0x8, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x18, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "packssdw %%xmm1, %%xmm1\n\t" - "packuswb %%xmm1, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz sse2_delta8_abgr_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" - ); + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_abgr_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_abgr_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3734,52 +3734,52 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "movdqa %4, %%xmm5\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "ssse3_delta8_rgba_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm3\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x8, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm1, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "pshufb %%xmm5, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz ssse3_delta8_rgba_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" - ); + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_rgba_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_rgba_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3789,52 +3789,52 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "movdqa %4, %%xmm5\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "ssse3_delta8_bgra_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm3\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x8, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "pshufb %%xmm5, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz ssse3_delta8_bgra_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" - ); + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_bgra_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_bgra_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3844,53 +3844,53 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "movdqa %4, %%xmm5\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "ssse3_delta8_argb_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm3\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "psrld $0x8, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm1, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x18, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "pshufb %%xmm5, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz ssse3_delta8_argb_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" - ); + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_argb_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_argb_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3900,53 +3900,53 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "movdqa %4, %%xmm5\n\t" - "sub $0x10, %0\n\t" - "sub $0x10, %1\n\t" - "sub $0x4, %2\n\t" - "ssse3_delta8_abgr_iter:\n\t" - "movdqa (%0,%3,4), %%xmm1\n\t" - "movdqa (%1,%3,4), %%xmm2\n\t" - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm3\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "psrld $0x8, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x18, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "pshufb %%xmm5, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%2,%3)\n\t" - "sub $0x4, %3\n\t" - "jnz ssse3_delta8_abgr_iter\n\t" - : - : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" - ); + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_abgr_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_abgr_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -3955,198 +3955,198 @@ void ssse3_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result /* RGB24 to grayscale */ __attribute__((noinline)) void std_convert_rgb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - r = col1[0]; - g = col1[1]; - b = col1[2]; - result[0] = (r + r + b + g + g + g + g + g)>>3; - r = col1[3]; - g = col1[4]; - b = col1[5]; - result[1] = (r + r + b + g + g + g + g + g)>>3; - r = col1[6]; - g = col1[7]; - b = col1[8]; - result[2] = (r + r + b + g + g + g + g + g)>>3; - r = col1[9]; - g = col1[10]; - b = col1[11]; - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 12; - result += 4; - } + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = col1[0]; + g = col1[1]; + b = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = col1[3]; + g = col1[4]; + b = col1[5]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = col1[6]; + g = col1[7]; + b = col1[8]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = col1[9]; + g = col1[10]; + b = col1[11]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + result += 4; + } } /* BGR24 to grayscale */ __attribute__((noinline)) void std_convert_bgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - b = col1[0]; - g = col1[1]; - r = col1[2]; - result[0] = (r + r + b + g + g + g + g + g)>>3; - b = col1[3]; - g = col1[4]; - r = col1[5]; - result[1] = (r + r + b + g + g + g + g + g)>>3; - b = col1[6]; - g = col1[7]; - r = col1[8]; - result[2] = (r + r + b + g + g + g + g + g)>>3; - b = col1[9]; - g = col1[10]; - r = col1[11]; - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 12; - result += 4; - } + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = col1[0]; + g = col1[1]; + r = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = col1[3]; + g = col1[4]; + r = col1[5]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = col1[6]; + g = col1[7]; + r = col1[8]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = col1[9]; + g = col1[10]; + r = col1[11]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + result += 4; + } } /* RGBA to grayscale */ __attribute__((noinline)) void std_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - r = col1[0]; - g = col1[1]; - b = col1[2]; - result[0] = (r + r + b + g + g + g + g + g)>>3; - r = col1[4]; - g = col1[5]; - b = col1[6]; - result[1] = (r + r + b + g + g + g + g + g)>>3; - r = col1[8]; - g = col1[9]; - b = col1[10]; - result[2] = (r + r + b + g + g + g + g + g)>>3; - r = col1[12]; - g = col1[13]; - b = col1[14]; - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - result += 4; - } + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = col1[0]; + g = col1[1]; + b = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = col1[4]; + g = col1[5]; + b = col1[6]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = col1[8]; + g = col1[9]; + b = col1[10]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = col1[12]; + g = col1[13]; + b = col1[14]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } } /* BGRA to grayscale */ __attribute__((noinline)) void std_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - b = col1[0]; - g = col1[1]; - r = col1[2]; - result[0] = (r + r + b + g + g + g + g + g)>>3; - b = col1[4]; - g = col1[5]; - r = col1[6]; - result[1] = (r + r + b + g + g + g + g + g)>>3; - b = col1[8]; - g = col1[9]; - r = col1[10]; - result[2] = (r + r + b + g + g + g + g + g)>>3; - b = col1[12]; - g = col1[13]; - r = col1[14]; - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - result += 4; - } + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = col1[0]; + g = col1[1]; + r = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = col1[4]; + g = col1[5]; + r = col1[6]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = col1[8]; + g = col1[9]; + r = col1[10]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = col1[12]; + g = col1[13]; + r = col1[14]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } } /* ARGB to grayscale */ __attribute__((noinline)) void std_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - r = col1[1]; - g = col1[2]; - b = col1[3]; - result[0] = (r + r + b + g + g + g + g + g)>>3; - r = col1[5]; - g = col1[6]; - b = col1[7]; - result[1] = (r + r + b + g + g + g + g + g)>>3; - r = col1[9]; - g = col1[10]; - b = col1[11]; - result[2] = (r + r + b + g + g + g + g + g)>>3; - r = col1[13]; - g = col1[14]; - b = col1[15]; - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - result += 4; - } + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = col1[1]; + g = col1[2]; + b = col1[3]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = col1[5]; + g = col1[6]; + b = col1[7]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = col1[9]; + g = col1[10]; + b = col1[11]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = col1[13]; + g = col1[14]; + b = col1[15]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } } /* ABGR to grayscale */ __attribute__((noinline)) void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - b = col1[1]; - g = col1[2]; - r = col1[3]; - result[0] = (r + r + b + g + g + g + g + g)>>3; - b = col1[5]; - g = col1[6]; - r = col1[7]; - result[1] = (r + r + b + g + g + g + g + g)>>3; - b = col1[9]; - g = col1[10]; - r = col1[11]; - result[2] = (r + r + b + g + g + g + g + g)>>3; - b = col1[13]; - g = col1[14]; - r = col1[15]; - result[3] = (r + r + b + g + g + g + g + g)>>3; - - col1 += 16; - result += 4; - } + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = col1[1]; + g = col1[2]; + r = col1[3]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = col1[5]; + g = col1[6]; + r = col1[7]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = col1[9]; + g = col1[10]; + r = col1[11]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = col1[13]; + g = col1[14]; + r = col1[15]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } } /* Converts a YUYV image into grayscale by extracting the Y channel */ __attribute__((noinline)) void std_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { - const uint16_t* yuvbuf = (const uint16_t*)col1; - const uint8_t* const max_ptr = result + count; - - while(result < max_ptr) { - result[0] = (uint8_t)yuvbuf[0]; - result[1] = (uint8_t)yuvbuf[1]; - result[2] = (uint8_t)yuvbuf[2]; - result[3] = (uint8_t)yuvbuf[3]; - result[4] = (uint8_t)yuvbuf[4]; - result[5] = (uint8_t)yuvbuf[5]; - result[6] = (uint8_t)yuvbuf[6]; - result[7] = (uint8_t)yuvbuf[7]; - result[8] = (uint8_t)yuvbuf[8]; - result[9] = (uint8_t)yuvbuf[9]; - result[10] = (uint8_t)yuvbuf[10]; - result[11] = (uint8_t)yuvbuf[11]; - result[12] = (uint8_t)yuvbuf[12]; - result[13] = (uint8_t)yuvbuf[13]; - result[14] = (uint8_t)yuvbuf[14]; - result[15] = (uint8_t)yuvbuf[15]; - - yuvbuf += 16; - result += 16; - } + const uint16_t* yuvbuf = (const uint16_t*)col1; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + result[0] = (uint8_t)yuvbuf[0]; + result[1] = (uint8_t)yuvbuf[1]; + result[2] = (uint8_t)yuvbuf[2]; + result[3] = (uint8_t)yuvbuf[3]; + result[4] = (uint8_t)yuvbuf[4]; + result[5] = (uint8_t)yuvbuf[5]; + result[6] = (uint8_t)yuvbuf[6]; + result[7] = (uint8_t)yuvbuf[7]; + result[8] = (uint8_t)yuvbuf[8]; + result[9] = (uint8_t)yuvbuf[9]; + result[10] = (uint8_t)yuvbuf[10]; + result[11] = (uint8_t)yuvbuf[11]; + result[12] = (uint8_t)yuvbuf[12]; + result[13] = (uint8_t)yuvbuf[13]; + result[14] = (uint8_t)yuvbuf[14]; + result[15] = (uint8_t)yuvbuf[15]; + + yuvbuf += 16; + result += 16; + } } /* RGBA to grayscale SSSE3 */ @@ -4156,45 +4156,45 @@ __attribute__((noinline,__target__("ssse3"))) void ssse3_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "mov $0xff, %%eax\n\t" - "movd %%eax, %%xmm0\n\t" - "pshufd $0x0, %%xmm0, %%xmm0\n\t" - "movdqa %3, %%xmm5\n\t" - "sub $0x10, %0\n\t" - "sub $0x4, %1\n\t" - "ssse3_convert_rgba_gray8_iter:\n\t" - "movdqa (%0,%2,4), %%xmm3\n\t" - "psrlq $0x3, %%xmm3\n\t" - "pand %%xmm4, %%xmm3\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x8, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "pslld $0x2, %%xmm2\n\t" - "paddd %%xmm1, %%xmm2\n\t" - "movdqa %%xmm3, %%xmm1\n\t" - "pand %%xmm0, %%xmm1\n\t" - "paddd %%xmm1, %%xmm1\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "movdqa %%xmm3, %%xmm2\n\t" - "psrld $0x10, %%xmm2\n\t" - "pand %%xmm0, %%xmm2\n\t" - "paddd %%xmm2, %%xmm1\n\t" - "pshufb %%xmm5, %%xmm1\n\t" - "movd %%xmm1, %%eax\n\t" - "movnti %%eax, (%1,%2)\n\t" - "sub $0x4, %2\n\t" - "jnz ssse3_convert_rgba_gray8_iter\n\t" - : - : "r" (col1), "r" (result), "r" (count), "m" (*movemask) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" - ); + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %3, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x4, %1\n\t" + "ssse3_convert_rgba_gray8_iter:\n\t" + "movdqa (%0,%2,4), %%xmm3\n\t" + "psrlq $0x3, %%xmm3\n\t" + "pand %%xmm4, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%1,%2)\n\t" + "sub $0x4, %2\n\t" + "jnz ssse3_convert_rgba_gray8_iter\n\t" + : + : "r" (col1), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -4204,156 +4204,156 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - unsigned long i = 0; + unsigned long i = 0; - __attribute__((aligned(16))) static const uint8_t movemask1[16] = {0,2,4,6,8,10,12,14,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - __attribute__((aligned(16))) static const uint8_t movemask2[16] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,2,4,6,8,10,12,14}; - - /* XMM0 - General purpose */ - /* XMM1 - General purpose */ - /* XMM2 - unused */ - /* XMM3 - shift mask 1 */ - /* XMM4 - shift mask 2 */ - /* XMM5 - unused*/ - /* XMM6 - unused */ - /* XMM7 - unused */ + __attribute__((aligned(16))) static const uint8_t movemask1[16] = {0,2,4,6,8,10,12,14,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,2,4,6,8,10,12,14}; + + /* XMM0 - General purpose */ + /* XMM1 - General purpose */ + /* XMM2 - unused */ + /* XMM3 - shift mask 1 */ + /* XMM4 - shift mask 2 */ + /* XMM5 - unused*/ + /* XMM6 - unused */ + /* XMM7 - unused */ - __asm__ __volatile__ ( - "movdqa %4, %%xmm3\n\t" - "movdqa %5, %%xmm4\n\t" - "algo_ssse3_convert_yuyv_gray8:\n\t" - "movdqa (%0), %%xmm0\n\t" - "pshufb %%xmm3, %%xmm0\n\t" - "movdqa 0x10(%0), %%xmm1\n\t" - "pshufb %%xmm4, %%xmm1\n\t" - "por %%xmm1, %%xmm0\n\t" - "movntdq %%xmm0, (%1)\n\t" - "add $0x10, %3\n\t" - "add $0x10, %1\n\t" - "add $0x20, %0\n\t" - "cmp %2, %3\n\t" - "jb algo_ssse3_convert_yuyv_gray8\n\t" - : + __asm__ __volatile__ ( + "movdqa %4, %%xmm3\n\t" + "movdqa %5, %%xmm4\n\t" + "algo_ssse3_convert_yuyv_gray8:\n\t" + "movdqa (%0), %%xmm0\n\t" + "pshufb %%xmm3, %%xmm0\n\t" + "movdqa 0x10(%0), %%xmm1\n\t" + "pshufb %%xmm4, %%xmm1\n\t" + "por %%xmm1, %%xmm0\n\t" + "movntdq %%xmm0, (%1)\n\t" + "add $0x10, %3\n\t" + "add $0x10, %1\n\t" + "add $0x20, %0\n\t" + "cmp %2, %3\n\t" + "jb algo_ssse3_convert_yuyv_gray8\n\t" + : #if (defined(_DEBUG) && !defined(__x86_64__)) /* Use one less register to allow compilation to success on 32bit with omit frame pointer disabled */ - : "r" (col1), "r" (result), "m" (count), "r" (i), "m" (*movemask1), "m" (*movemask2) + : "r" (col1), "r" (result), "m" (count), "r" (i), "m" (*movemask1), "m" (*movemask2) #else - : "r" (col1), "r" (result), "r" (count), "r" (i), "m" (*movemask1), "m" (*movemask2) + : "r" (col1), "r" (result), "r" (count), "r" (i), "m" (*movemask1), "m" (*movemask2) #endif - : "%xmm3", "%xmm4", "cc", "memory" - ); + : "%xmm3", "%xmm4", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } /* YUYV to RGB24 - relocated from zm_local_camera.cpp */ __attribute__((noinline)) void zm_convert_yuyv_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - unsigned int y1,y2,u,v; - for(unsigned int i=0; i < count; i += 2, col1 += 4, result += 6) { - y1 = col1[0]; - u = col1[1]; - y2 = col1[2]; - v = col1[3]; + unsigned int r,g,b; + unsigned int y1,y2,u,v; + for(unsigned int i=0; i < count; i += 2, col1 += 4, result += 6) { + y1 = col1[0]; + u = col1[1]; + y2 = col1[2]; + v = col1[3]; - r = y1 + r_v_table[v]; - g = y1 - (g_u_table[u]+g_v_table[v]); - b = y1 + b_u_table[u]; - - result[0] = r<0?0:(r>255?255:r); - result[1] = g<0?0:(g>255?255:g); - result[2] = b<0?0:(b>255?255:b); - - r = y2 + r_v_table[v]; - g = y2 - (g_u_table[u]+g_v_table[v]); - b = y2 + b_u_table[u]; + r = y1 + r_v_table[v]; + g = y1 - (g_u_table[u]+g_v_table[v]); + b = y1 + b_u_table[u]; + + result[0] = r<0?0:(r>255?255:r); + result[1] = g<0?0:(g>255?255:g); + result[2] = b<0?0:(b>255?255:b); + + r = y2 + r_v_table[v]; + g = y2 - (g_u_table[u]+g_v_table[v]); + b = y2 + b_u_table[u]; - result[3] = r<0?0:(r>255?255:r); - result[4] = g<0?0:(g>255?255:g); - result[5] = b<0?0:(b>255?255:b); - } - + result[3] = r<0?0:(r>255?255:r); + result[4] = g<0?0:(g>255?255:g); + result[5] = b<0?0:(b>255?255:b); + } + } /* YUYV to RGBA - modified the one above */ __attribute__((noinline)) void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - unsigned int y1,y2,u,v; - for(unsigned int i=0; i < count; i += 2, col1 += 4, result += 8) { - y1 = col1[0]; - u = col1[1]; - y2 = col1[2]; - v = col1[3]; + unsigned int r,g,b; + unsigned int y1,y2,u,v; + for(unsigned int i=0; i < count; i += 2, col1 += 4, result += 8) { + y1 = col1[0]; + u = col1[1]; + y2 = col1[2]; + v = col1[3]; - r = y1 + r_v_table[v]; - g = y1 - (g_u_table[u]+g_v_table[v]); - b = y1 + b_u_table[u]; - - result[0] = r<0?0:(r>255?255:r); - result[1] = g<0?0:(g>255?255:g); - result[2] = b<0?0:(b>255?255:b); - - r = y2 + r_v_table[v]; - g = y2 - (g_u_table[u]+g_v_table[v]); - b = y2 + b_u_table[u]; + r = y1 + r_v_table[v]; + g = y1 - (g_u_table[u]+g_v_table[v]); + b = y1 + b_u_table[u]; + + result[0] = r<0?0:(r>255?255:r); + result[1] = g<0?0:(g>255?255:g); + result[2] = b<0?0:(b>255?255:b); + + r = y2 + r_v_table[v]; + g = y2 - (g_u_table[u]+g_v_table[v]); + b = y2 + b_u_table[u]; - result[4] = r<0?0:(r>255?255:r); - result[5] = g<0?0:(g>255?255:g); - result[6] = b<0?0:(b>255?255:b); - } - + result[4] = r<0?0:(r>255?255:r); + result[5] = g<0?0:(g>255?255:g); + result[6] = b<0?0:(b>255?255:b); + } + } /* RGB555 to RGB24 - relocated from zm_local_camera.cpp */ __attribute__((noinline)) void zm_convert_rgb555_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { - b = ((*col1)<<3)&0xf8; - g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; - r = ((*(col1+1))<<1)&0xf8; - result[0] = r; - result[1] = g; - result[2] = b; - } + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; + r = ((*(col1+1))<<1)&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } } /* RGB555 to RGBA - modified the one above */ __attribute__((noinline)) void zm_convert_rgb555_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { - b = ((*col1)<<3)&0xf8; - g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; - r = ((*(col1+1))<<1)&0xf8; - result[0] = r; - result[1] = g; - result[2] = b; - } + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; + r = ((*(col1+1))<<1)&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } } /* RGB565 to RGB24 - relocated from zm_local_camera.cpp */ __attribute__((noinline)) void zm_convert_rgb565_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { - b = ((*col1)<<3)&0xf8; - g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; - r = (*(col1+1))&0xf8; - result[0] = r; - result[1] = g; - result[2] = b; - } + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; + r = (*(col1+1))&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } } /* RGB565 to RGBA - modified the one above */ __attribute__((noinline)) void zm_convert_rgb565_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { - unsigned int r,g,b; - for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { - b = ((*col1)<<3)&0xf8; - g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; - r = (*(col1+1))&0xf8; - result[0] = r; - result[1] = g; - result[2] = b; - } + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; + r = (*(col1+1))&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } } /************************************************* DEINTERLACE FUNCTIONS *************************************************/ @@ -4361,461 +4361,461 @@ __attribute__((noinline)) void zm_convert_rgb565_rgba(const uint8_t* col1, uint8 /* Grayscale */ __attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const uint8_t* const max_ptr = col1 + (width*(height-1)); - const uint8_t *max_ptr2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const uint8_t* const max_ptr = col1 + (width*(height-1)); + const uint8_t *max_ptr2; - pcurrent = col1 + width; - pncurrent = col2 + width; - pabove = col1; - pnabove = col2; - pbelow = col1 + (width*2); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + width; - while(pcurrent < max_ptr2) { - if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { - *pcurrent = (*pabove + *pbelow) >> 1; - } - pabove++; - pnabove++; - pcurrent++; - pncurrent++; - pbelow++; - } - pcurrent += width; - pncurrent += width; - pabove += width; - pnabove += width; - pbelow += width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + width; - while(pcurrent < max_ptr2) { - if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { - *pcurrent = *pabove; - } - pabove++; - pnabove++; - pcurrent++; - pncurrent++; - } + pcurrent = col1 + width; + pncurrent = col2 + width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + width; + while(pcurrent < max_ptr2) { + if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { + *pcurrent = (*pabove + *pbelow) >> 1; + } + pabove++; + pnabove++; + pcurrent++; + pncurrent++; + pbelow++; + } + pcurrent += width; + pncurrent += width; + pabove += width; + pnabove += width; + pbelow += width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + width; + while(pcurrent < max_ptr2) { + if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { + *pcurrent = *pabove; + } + pabove++; + pnabove++; + pcurrent++; + pncurrent++; + } } /* RGB */ __attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const unsigned int row_width = width*3; - const uint8_t* const max_ptr = col1 + (row_width * (height-1)); - const uint8_t *max_ptr2; - unsigned int b, g, r; - unsigned int delta1, delta2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*3; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; - pcurrent = col1 + (width*3); - pncurrent = col2 + (width*3); - pabove = col1; - pnabove = col2; - pbelow = col1 + ((width*2)*3); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - r = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - b = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - r = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - b = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; - pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; - pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; - } - pabove += 3; - pnabove += 3; - pcurrent += 3; - pncurrent += 3; - pbelow += 3; - } - pcurrent += row_width; - pncurrent += row_width; - pabove += row_width; - pnabove += row_width; - pbelow += row_width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - r = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - b = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - r = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - b = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = pabove[0]; - pcurrent[1] = pabove[1]; - pcurrent[2] = pabove[2]; - } - pabove += 3; - pnabove += 3; - pcurrent += 3; - pncurrent += 3; - } + pcurrent = col1 + (width*3); + pncurrent = col2 + (width*3); + pabove = col1; + pnabove = col2; + pbelow = col1 + ((width*2)*3); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + pbelow += 3; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + } } /* BGR */ __attribute__((noinline)) void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const unsigned int row_width = width*3; - const uint8_t* const max_ptr = col1 + (row_width * (height-1)); - const uint8_t *max_ptr2; - unsigned int b, g, r; - unsigned int delta1, delta2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*3; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; - pcurrent = col1 + (width*3); - pncurrent = col2 + (width*3); - pabove = col1; - pnabove = col2; - pbelow = col1 + ((width*2)*3); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - b = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - r = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - b = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - r = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; - pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; - pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; - } - pabove += 3; - pnabove += 3; - pcurrent += 3; - pncurrent += 3; - pbelow += 3; - } - pcurrent += row_width; - pncurrent += row_width; - pabove += row_width; - pnabove += row_width; - pbelow += row_width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - b = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - r = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - b = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - r = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = pabove[0]; - pcurrent[1] = pabove[1]; - pcurrent[2] = pabove[2]; - } - pabove += 3; - pnabove += 3; - pcurrent += 3; - pncurrent += 3; - } + pcurrent = col1 + (width*3); + pncurrent = col2 + (width*3); + pabove = col1; + pnabove = col2; + pbelow = col1 + ((width*2)*3); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + pbelow += 3; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + } } /* RGBA */ __attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const unsigned int row_width = width*4; - const uint8_t* const max_ptr = col1 + (row_width * (height-1)); - const uint8_t *max_ptr2; - unsigned int b, g, r; - unsigned int delta1, delta2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; - pcurrent = col1 + row_width; - pncurrent = col2 + row_width; - pabove = col1; - pnabove = col2; - pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - r = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - b = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - r = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - b = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; - pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; - pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - pbelow += 4; - } - pcurrent += row_width; - pncurrent += row_width; - pabove += row_width; - pnabove += row_width; - pbelow += row_width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - r = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - b = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - r = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - b = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = pabove[0]; - pcurrent[1] = pabove[1]; - pcurrent[2] = pabove[2]; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - } + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } } /* BGRA */ __attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const unsigned int row_width = width*4; - const uint8_t* const max_ptr = col1 + (row_width * (height-1)); - const uint8_t *max_ptr2; - unsigned int b, g, r; - unsigned int delta1, delta2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; - pcurrent = col1 + row_width; - pncurrent = col2 + row_width; - pabove = col1; - pnabove = col2; - pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - b = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - r = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - b = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - r = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; - pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; - pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - pbelow += 4; - } - pcurrent += row_width; - pncurrent += row_width; - pabove += row_width; - pnabove += row_width; - pbelow += row_width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - b = abs(pnabove[0] - pabove[0]); - g = abs(pnabove[1] - pabove[1]); - r = abs(pnabove[2] - pabove[2]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - b = abs(pncurrent[0] - pcurrent[0]); - g = abs(pncurrent[1] - pcurrent[1]); - r = abs(pncurrent[2] - pcurrent[2]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[0] = pabove[0]; - pcurrent[1] = pabove[1]; - pcurrent[2] = pabove[2]; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - } + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } } /* ARGB */ __attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const unsigned int row_width = width*4; - const uint8_t* const max_ptr = col1 + (row_width * (height-1)); - const uint8_t *max_ptr2; - unsigned int b, g, r; - unsigned int delta1, delta2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; - pcurrent = col1 + row_width; - pncurrent = col2 + row_width; - pabove = col1; - pnabove = col2; - pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - r = abs(pnabove[1] - pabove[1]); - g = abs(pnabove[2] - pabove[2]); - b = abs(pnabove[3] - pabove[3]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - r = abs(pncurrent[1] - pcurrent[1]); - g = abs(pncurrent[2] - pcurrent[2]); - b = abs(pncurrent[3] - pcurrent[3]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; - pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; - pcurrent[3] = (pabove[3] + pbelow[3]) >> 1; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - pbelow += 4; - } - pcurrent += row_width; - pncurrent += row_width; - pabove += row_width; - pnabove += row_width; - pbelow += row_width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - r = abs(pnabove[1] - pabove[1]); - g = abs(pnabove[2] - pabove[2]); - b = abs(pnabove[3] - pabove[3]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - r = abs(pncurrent[1] - pcurrent[1]); - g = abs(pncurrent[2] - pcurrent[2]); - b = abs(pncurrent[3] - pcurrent[3]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[1] = pabove[1]; - pcurrent[2] = pabove[2]; - pcurrent[3] = pabove[3]; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - } + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + b = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + b = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + pcurrent[3] = (pabove[3] + pbelow[3]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + b = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + b = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + pcurrent[3] = pabove[3]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } } /* ABGR */ __attribute__((noinline)) void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { - uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; - const unsigned int row_width = width*4; - const uint8_t* const max_ptr = col1 + (row_width * (height-1)); - const uint8_t *max_ptr2; - unsigned int b, g, r; - unsigned int delta1, delta2; + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; - pcurrent = col1 + row_width; - pncurrent = col2 + row_width; - pabove = col1; - pnabove = col2; - pbelow = col1 + (row_width*2); - while(pcurrent < max_ptr) - { - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - b = abs(pnabove[1] - pabove[1]); - g = abs(pnabove[2] - pabove[2]); - r = abs(pnabove[3] - pabove[3]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - b = abs(pncurrent[1] - pcurrent[1]); - g = abs(pncurrent[2] - pcurrent[2]); - r = abs(pncurrent[3] - pcurrent[3]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; - pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; - pcurrent[3] = (pabove[3] + pbelow[3]) >> 1; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - pbelow += 4; - } - pcurrent += row_width; - pncurrent += row_width; - pabove += row_width; - pnabove += row_width; - pbelow += row_width; - - } - - /* Special case for the last line */ - max_ptr2 = pcurrent + row_width; - while(pcurrent < max_ptr2) { - b = abs(pnabove[1] - pabove[1]); - g = abs(pnabove[2] - pabove[2]); - r = abs(pnabove[3] - pabove[3]); - delta1 = (r + r + b + g + g + g + g + g)>>3; - b = abs(pncurrent[1] - pcurrent[1]); - g = abs(pncurrent[2] - pcurrent[2]); - r = abs(pncurrent[3] - pcurrent[3]); - delta2 = (r + r + b + g + g + g + g + g)>>3; - if(((delta1 + delta2) >> 1) >= threshold) { - pcurrent[1] = pabove[1]; - pcurrent[2] = pabove[2]; - pcurrent[3] = pabove[3]; - } - pabove += 4; - pnabove += 4; - pcurrent += 4; - pncurrent += 4; - } + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + r = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + r = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + pcurrent[3] = (pabove[3] + pbelow[3]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + r = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + r = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + pcurrent[3] = pabove[3]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } } /* Grayscale SSSE3 */ @@ -4825,132 +4825,132 @@ __attribute__((noinline,__target__("ssse3"))) void ssse3_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - union { - uint32_t int32; - uint8_t int8a[4]; - } threshold_mask; - threshold_mask.int8a[0] = threshold; - threshold_mask.int8a[1] = 0; - threshold_mask.int8a[2] = threshold; - threshold_mask.int8a[3] = 0; + union { + uint32_t int32; + uint8_t int8a[4]; + } threshold_mask; + threshold_mask.int8a[0] = threshold; + threshold_mask.int8a[1] = 0; + threshold_mask.int8a[2] = threshold; + threshold_mask.int8a[3] = 0; - unsigned long row_width = width; - uint8_t* max_ptr = col1 + (row_width * (height-2)); - uint8_t* max_ptr2 = col1 + row_width; + unsigned long row_width = width; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; - __asm__ __volatile__ ( - /* Load the threshold */ - "mov %5, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - /* Zero the temporary register */ - "pxor %%xmm0, %%xmm0\n\t" + __asm__ __volatile__ ( + /* Load the threshold */ + "mov %5, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" - "algo_ssse3_deinterlace_4field_gray8:\n\t" + "algo_ssse3_deinterlace_4field_gray8:\n\t" - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "pmaxub %%xmm2, %%xmm1\n\t" - "pminub %%xmm5, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "pmaxub %%xmm2, %%xmm1\n\t" + "pminub %%xmm5, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "pmaxub %%xmm2, %%xmm1\n\t" - "pminub %%xmm6, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "pmaxub %%xmm2, %%xmm1\n\t" + "pminub %%xmm6, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together - "movdqa %%xmm1, %%xmm2\n\t" + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "movdqa %%xmm1, %%xmm2\n\t" - /* Do the comparison on words instead of bytes because we don't have unsigned comparison */ - "punpcklbw %%xmm0, %%xmm1\n\t" // Expand pixels 0-7 into words into xmm1 - "punpckhbw %%xmm0, %%xmm2\n\t" // Expand pixels 8-15 into words into xmm2 - "pcmpgtw %%xmm4, %%xmm1\n\t" // Compare average delta with threshold for pixels 0-7 - "pcmpgtw %%xmm4, %%xmm2\n\t" // Compare average delta with threshold for pixels 8-15 - "packsswb %%xmm2, %%xmm1\n\t" // Pack the comparison results into xmm1 + /* Do the comparison on words instead of bytes because we don't have unsigned comparison */ + "punpcklbw %%xmm0, %%xmm1\n\t" // Expand pixels 0-7 into words into xmm1 + "punpckhbw %%xmm0, %%xmm2\n\t" // Expand pixels 8-15 into words into xmm2 + "pcmpgtw %%xmm4, %%xmm1\n\t" // Compare average delta with threshold for pixels 0-7 + "pcmpgtw %%xmm4, %%xmm2\n\t" // Compare average delta with threshold for pixels 8-15 + "packsswb %%xmm2, %%xmm1\n\t" // Pack the comparison results into xmm1 - "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow - "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow - "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - "sub %4, %0\n\t" // Restore pcurrent to pabove - "sub %4, %1\n\t" // Restore pncurrent to pnabove + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove - /* Next pixels */ - "add $0x10, %0\n\t" // Add 16 to pcurrent - "add $0x10, %1\n\t" // Add 16 to pncurrent + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent - /* Check if we reached the row end */ - "cmp %2, %0\n\t" - "jb algo_ssse3_deinterlace_4field_gray8\n\t" // Go for another iteration + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_gray8\n\t" // Go for another iteration - /* Next row */ - "add %4, %0\n\t" // Add width to pcurrent - "add %4, %1\n\t" // Add width to pncurrent - "mov %0, %2\n\t" - "add %4, %2\n\t" // Add width to max_ptr2 + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 - /* Check if we reached the end */ - "cmp %3, %0\n\t" - "jb algo_ssse3_deinterlace_4field_gray8\n\t" // Go for another iteration + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_gray8\n\t" // Go for another iteration - /* Special case for the last line */ - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "pmaxub %%xmm2, %%xmm1\n\t" - "pminub %%xmm5, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "pmaxub %%xmm2, %%xmm1\n\t" + "pminub %%xmm5, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "pmaxub %%xmm2, %%xmm1\n\t" - "pminub %%xmm6, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "pmaxub %%xmm2, %%xmm1\n\t" + "pminub %%xmm6, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together - "movdqa %%xmm1, %%xmm2\n\t" + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "movdqa %%xmm1, %%xmm2\n\t" - /* Do the comparison on words instead of bytes because we don't have unsigned comparison */ - "punpcklbw %%xmm0, %%xmm1\n\t" // Expand pixels 0-7 into words into xmm1 - "punpckhbw %%xmm0, %%xmm2\n\t" // Expand pixels 8-15 into words into xmm2 - "pcmpgtw %%xmm4, %%xmm1\n\t" // Compare average delta with threshold for pixels 0-7 - "pcmpgtw %%xmm4, %%xmm2\n\t" // Compare average delta with threshold for pixels 8-15 - "packsswb %%xmm2, %%xmm1\n\t" // Pack the comparison results into xmm1 + /* Do the comparison on words instead of bytes because we don't have unsigned comparison */ + "punpcklbw %%xmm0, %%xmm1\n\t" // Expand pixels 0-7 into words into xmm1 + "punpckhbw %%xmm0, %%xmm2\n\t" // Expand pixels 8-15 into words into xmm2 + "pcmpgtw %%xmm4, %%xmm1\n\t" // Compare average delta with threshold for pixels 0-7 + "pcmpgtw %%xmm4, %%xmm2\n\t" // Compare average delta with threshold for pixels 8-15 + "packsswb %%xmm2, %%xmm1\n\t" // Pack the comparison results into xmm1 - "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - : - : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_mask.int32) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" - ); + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_mask.int32) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -4960,180 +4960,180 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __attribute__((aligned(16))) static const uint8_t movemask2[16] = {1,1,1,1,1,0,0,2,9,9,9,9,9,8,8,10}; + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {1,1,1,1,1,0,0,2,9,9,9,9,9,8,8,10}; - const uint32_t threshold_val = threshold; + const uint32_t threshold_val = threshold; - unsigned long row_width = width*4; - uint8_t* max_ptr = col1 + (row_width * (height-2)); - uint8_t* max_ptr2 = col1 + row_width; + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "movdqa %6, %%xmm3\n\t" - "mov %5, %%eax\n\t" + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" #if defined(__x86_64__) - "movd %%eax, %%xmm8\n\t" - "pshufd $0x0, %%xmm8, %%xmm8\n\t" + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" #endif - /* Zero the temporary register */ - "pxor %%xmm0, %%xmm0\n\t" + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" - "algo_ssse3_deinterlace_4field_rgba:\n\t" + "algo_ssse3_deinterlace_4field_rgba:\n\t" - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow - "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow - "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - "sub %4, %0\n\t" // Restore pcurrent to pabove - "sub %4, %1\n\t" // Restore pncurrent to pnabove + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove - /* Next pixels */ - "add $0x10, %0\n\t" // Add 16 to pcurrent - "add $0x10, %1\n\t" // Add 16 to pncurrent + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent - /* Check if we reached the row end */ - "cmp %2, %0\n\t" - "jb algo_ssse3_deinterlace_4field_rgba\n\t" // Go for another iteration + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_rgba\n\t" // Go for another iteration - /* Next row */ - "add %4, %0\n\t" // Add width to pcurrent - "add %4, %1\n\t" // Add width to pncurrent - "mov %0, %2\n\t" - "add %4, %2\n\t" // Add width to max_ptr2 + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 - /* Check if we reached the end */ - "cmp %3, %0\n\t" - "jb algo_ssse3_deinterlace_4field_rgba\n\t" // Go for another iteration + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_rgba\n\t" // Go for another iteration - /* Special case for the last line */ - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - : - : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) #if defined(__x86_64__) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" #else - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" #endif - ); + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -5143,180 +5143,180 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __attribute__((aligned(16))) static const uint8_t movemask2[16] = {1,1,1,1,1,2,2,0,9,9,9,9,9,10,10,8}; + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {1,1,1,1,1,2,2,0,9,9,9,9,9,10,10,8}; - const uint32_t threshold_val = threshold; + const uint32_t threshold_val = threshold; - unsigned long row_width = width*4; - uint8_t* max_ptr = col1 + (row_width * (height-2)); - uint8_t* max_ptr2 = col1 + row_width; + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "movdqa %6, %%xmm3\n\t" - "mov %5, %%eax\n\t" + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" #if defined(__x86_64__) - "movd %%eax, %%xmm8\n\t" - "pshufd $0x0, %%xmm8, %%xmm8\n\t" + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" #endif - /* Zero the temporary register */ - "pxor %%xmm0, %%xmm0\n\t" + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" - "algo_ssse3_deinterlace_4field_bgra:\n\t" + "algo_ssse3_deinterlace_4field_bgra:\n\t" - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow - "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow - "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - "sub %4, %0\n\t" // Restore pcurrent to pabove - "sub %4, %1\n\t" // Restore pncurrent to pnabove + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove - /* Next pixels */ - "add $0x10, %0\n\t" // Add 16 to pcurrent - "add $0x10, %1\n\t" // Add 16 to pncurrent + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent - /* Check if we reached the row end */ - "cmp %2, %0\n\t" - "jb algo_ssse3_deinterlace_4field_bgra\n\t" // Go for another iteration + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_bgra\n\t" // Go for another iteration - /* Next row */ - "add %4, %0\n\t" // Add width to pcurrent - "add %4, %1\n\t" // Add width to pncurrent - "mov %0, %2\n\t" - "add %4, %2\n\t" // Add width to max_ptr2 + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 - /* Check if we reached the end */ - "cmp %3, %0\n\t" - "jb algo_ssse3_deinterlace_4field_bgra\n\t" // Go for another iteration + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_bgra\n\t" // Go for another iteration - /* Special case for the last line */ - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - : - : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) #if defined(__x86_64__) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" #else - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" #endif - ); + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -5326,180 +5326,180 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __attribute__((aligned(16))) static const uint8_t movemask2[16] = {2,2,2,2,2,1,1,3,10,10,10,10,10,9,9,11}; + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {2,2,2,2,2,1,1,3,10,10,10,10,10,9,9,11}; - const uint32_t threshold_val = threshold; + const uint32_t threshold_val = threshold; - unsigned long row_width = width*4; - uint8_t* max_ptr = col1 + (row_width * (height-2)); - uint8_t* max_ptr2 = col1 + row_width; + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "movdqa %6, %%xmm3\n\t" - "mov %5, %%eax\n\t" + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" #if defined(__x86_64__) - "movd %%eax, %%xmm8\n\t" - "pshufd $0x0, %%xmm8, %%xmm8\n\t" + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" #endif - /* Zero the temporary register */ - "pxor %%xmm0, %%xmm0\n\t" + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" - "algo_ssse3_deinterlace_4field_argb:\n\t" + "algo_ssse3_deinterlace_4field_argb:\n\t" - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow - "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow - "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - "sub %4, %0\n\t" // Restore pcurrent to pabove - "sub %4, %1\n\t" // Restore pncurrent to pnabove + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove - /* Next pixels */ - "add $0x10, %0\n\t" // Add 16 to pcurrent - "add $0x10, %1\n\t" // Add 16 to pncurrent + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent - /* Check if we reached the row end */ - "cmp %2, %0\n\t" - "jb algo_ssse3_deinterlace_4field_argb\n\t" // Go for another iteration + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_argb\n\t" // Go for another iteration - /* Next row */ - "add %4, %0\n\t" // Add width to pcurrent - "add %4, %1\n\t" // Add width to pncurrent - "mov %0, %2\n\t" - "add %4, %2\n\t" // Add width to max_ptr2 + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 - /* Check if we reached the end */ - "cmp %3, %0\n\t" - "jb algo_ssse3_deinterlace_4field_argb\n\t" // Go for another iteration + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_argb\n\t" // Go for another iteration - /* Special case for the last line */ - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - : - : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) #if defined(__x86_64__) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" #else - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" #endif - ); + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } @@ -5509,179 +5509,179 @@ __attribute__((noinline,__target__("ssse3"))) #endif void ssse3_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - __attribute__((aligned(16))) static const uint8_t movemask2[16] = {2,2,2,2,2,3,3,1,10,10,10,10,10,11,11,9}; + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {2,2,2,2,2,3,3,1,10,10,10,10,10,11,11,9}; - const uint32_t threshold_val = threshold; + const uint32_t threshold_val = threshold; - unsigned long row_width = width*4; - uint8_t* max_ptr = col1 + (row_width * (height-2)); - uint8_t* max_ptr2 = col1 + row_width; + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; - __asm__ __volatile__ ( - "mov $0x1F1F1F1F, %%eax\n\t" - "movd %%eax, %%xmm4\n\t" - "pshufd $0x0, %%xmm4, %%xmm4\n\t" - "movdqa %6, %%xmm3\n\t" - "mov %5, %%eax\n\t" + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" #if defined(__x86_64__) - "movd %%eax, %%xmm8\n\t" - "pshufd $0x0, %%xmm8, %%xmm8\n\t" + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" #endif - /* Zero the temporary register */ - "pxor %%xmm0, %%xmm0\n\t" + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" - "algo_ssse3_deinterlace_4field_abgr:\n\t" + "algo_ssse3_deinterlace_4field_abgr:\n\t" - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow - "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow - "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - "sub %4, %0\n\t" // Restore pcurrent to pabove - "sub %4, %1\n\t" // Restore pncurrent to pnabove + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove - /* Next pixels */ - "add $0x10, %0\n\t" // Add 16 to pcurrent - "add $0x10, %1\n\t" // Add 16 to pncurrent + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent - /* Check if we reached the row end */ - "cmp %2, %0\n\t" - "jb algo_ssse3_deinterlace_4field_abgr\n\t" // Go for another iteration + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_abgr\n\t" // Go for another iteration - /* Next row */ - "add %4, %0\n\t" // Add width to pcurrent - "add %4, %1\n\t" // Add width to pncurrent - "mov %0, %2\n\t" - "add %4, %2\n\t" // Add width to max_ptr2 + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 - /* Check if we reached the end */ - "cmp %3, %0\n\t" - "jb algo_ssse3_deinterlace_4field_abgr\n\t" // Go for another iteration + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_abgr\n\t" // Go for another iteration - /* Special case for the last line */ - /* Load pabove into xmm1 and pnabove into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" - "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ - /* Next row */ - "add %4, %0\n\t" - "add %4, %1\n\t" + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" - /* Load pcurrent into xmm1 and pncurrent into xmm2 */ - "movdqa (%0), %%xmm1\n\t" - "movdqa (%1), %%xmm2\n\t" - "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ - "psrlq $0x3, %%xmm1\n\t" - "psrlq $0x3, %%xmm2\n\t" - "pand %%xmm4, %%xmm1\n\t" - "pand %%xmm4, %%xmm2\n\t" - "psubb %%xmm2, %%xmm1\n\t" - "pabsb %%xmm1, %%xmm2\n\t" - "movdqa %%xmm2, %%xmm1\n\t" - "punpckldq %%xmm1, %%xmm1\n\t" - "pshufb %%xmm3, %%xmm1\n\t" - "psadbw %%xmm0, %%xmm1\n\t" - "punpckhdq %%xmm2, %%xmm2\n\t" - "pshufb %%xmm3, %%xmm2\n\t" - "psadbw %%xmm0, %%xmm2\n\t" - "packuswb %%xmm2, %%xmm1\n\t" + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" - "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together #if defined(__x86_64__) - "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold #else - "movd %%eax, %%xmm7\n\t" // Setup the threshold - "pshufd $0x0, %%xmm7, %%xmm7\n\t" + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" - "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold #endif - "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied - "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced - "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent - "movntdq %%xmm1, (%0)\n\t" // Write pcurrent - : - : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) #if defined(__x86_64__) - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" #else - : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" #endif - ); + ); #else - Panic("SSE function called on a non x86\\x86-64 platform"); + Panic("SSE function called on a non x86\\x86-64 platform"); #endif } diff --git a/src/zm_image_analyser.cpp b/src/zm_image_analyser.cpp index 1445e9864..8f03160d9 100644 --- a/src/zm_image_analyser.cpp +++ b/src/zm_image_analyser.cpp @@ -7,7 +7,7 @@ */ ImageAnalyser::ImageAnalyser(const ImageAnalyser& source) { - m_Detectors = source.m_Detectors; + m_Detectors = source.m_Detectors; } @@ -17,18 +17,18 @@ ImageAnalyser::ImageAnalyser(const ImageAnalyser& source) */ ImageAnalyser& ImageAnalyser::operator=(const ImageAnalyser& source) { - m_Detectors = source.m_Detectors; - return *this; + m_Detectors = source.m_Detectors; + return *this; } ImageAnalyser::~ImageAnalyser() { - for(DetectorsList::reverse_iterator It = m_Detectors.rbegin(); - It != m_Detectors.rend(); - ++It) - delete *It; + for(DetectorsList::reverse_iterator It = m_Detectors.rbegin(); + It != m_Detectors.rend(); + ++It) + delete *It; } @@ -42,23 +42,23 @@ ImageAnalyser::~ImageAnalyser() */ int ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, int n_numZones, Event::StringSetMap noteSetMap, std::string& det_cause) { - Event::StringSet zoneSet; - int score = 0; + Event::StringSet zoneSet; + int score = 0; - for(DetectorsList::iterator It = m_Detectors.begin(); - It != m_Detectors.end(); - ++It) + for(DetectorsList::iterator It = m_Detectors.begin(); + It != m_Detectors.end(); + ++It) + { + int detect_score = (*It)->Detect(comp_image, zones, n_numZones, zoneSet); + if (detect_score) { - int detect_score = (*It)->Detect(comp_image, zones, n_numZones, zoneSet); - if (detect_score) - { - score += detect_score; - noteSetMap[(*It)->getDetectionCause()] = zoneSet; - if (det_cause.length()) - det_cause += ", "; - det_cause += (*It)->getDetectionCause(); - } + score += detect_score; + noteSetMap[(*It)->getDetectionCause()] = zoneSet; + if (det_cause.length()) + det_cause += ", "; + det_cause += (*It)->getDetectionCause(); } - return score; + } + return score; } diff --git a/src/zm_image_analyser.h b/src/zm_image_analyser.h index 74cc7a73a..c853c82a3 100644 --- a/src/zm_image_analyser.h +++ b/src/zm_image_analyser.h @@ -22,18 +22,18 @@ using namespace std; //! Class for handling image detection. class ImageAnalyser { public: - - //!Default constructor. - ImageAnalyser() {}; + + //!Default constructor. + ImageAnalyser() {}; - //! Destructor. - ~ImageAnalyser(); + //! Destructor. + ~ImageAnalyser(); - //! Copy constructor. - ImageAnalyser(const ImageAnalyser& source); + //! Copy constructor. + ImageAnalyser(const ImageAnalyser& source); - //! Overloaded operator=. - ImageAnalyser& operator=(const ImageAnalyser& source); + //! Overloaded operator=. + ImageAnalyser& operator=(const ImageAnalyser& source); private: diff --git a/src/zm_jpeg.cpp b/src/zm_jpeg.cpp index 92f757ca1..c47bbe267 100644 --- a/src/zm_jpeg.cpp +++ b/src/zm_jpeg.cpp @@ -32,65 +32,65 @@ static int jpeg_err_count = 0; void zm_jpeg_error_exit( j_common_ptr cinfo ) { - static char buffer[JMSG_LENGTH_MAX]; - zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; + static char buffer[JMSG_LENGTH_MAX]; + zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; - (zmerr->pub.format_message)( cinfo, buffer ); + (zmerr->pub.format_message)( cinfo, buffer ); - Error( "%s", buffer ); - if ( ++jpeg_err_count == MAX_JPEG_ERRS ) - { - Fatal( "Maximum number (%d) of JPEG errors reached, exiting", jpeg_err_count ); - } + Error( "%s", buffer ); + if ( ++jpeg_err_count == MAX_JPEG_ERRS ) + { + Fatal( "Maximum number (%d) of JPEG errors reached, exiting", jpeg_err_count ); + } - longjmp( zmerr->setjmp_buffer, 1 ); + longjmp( zmerr->setjmp_buffer, 1 ); } void zm_jpeg_emit_message( j_common_ptr cinfo, int msg_level ) { - static char buffer[JMSG_LENGTH_MAX]; - zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; + static char buffer[JMSG_LENGTH_MAX]; + zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; - if ( msg_level < 0 ) - { - /* It's a warning message. Since corrupt files may generate many warnings, - * the policy implemented here is to show only the first warning, - * unless trace_level >= 3. - */ - if ( zmerr->pub.num_warnings == 0 || zmerr->pub.trace_level >= 3 ) - { - (zmerr->pub.format_message)( cinfo, buffer ); - if (!strstr(buffer, "Corrupt JPEG data:")) - Warning( "%s", buffer ); - } - /* Always count warnings in num_warnings. */ - zmerr->pub.num_warnings++; - } - else - { - /* It's a trace message. Show it if trace_level >= msg_level. */ - if ( zmerr->pub.trace_level >= msg_level ) - { - (zmerr->pub.format_message)( cinfo, buffer ); - Debug( msg_level, "%s", buffer ); - } - } + if ( msg_level < 0 ) + { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if ( zmerr->pub.num_warnings == 0 || zmerr->pub.trace_level >= 3 ) + { + (zmerr->pub.format_message)( cinfo, buffer ); + if (!strstr(buffer, "Corrupt JPEG data:")) + Warning( "%s", buffer ); + } + /* Always count warnings in num_warnings. */ + zmerr->pub.num_warnings++; + } + else + { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if ( zmerr->pub.trace_level >= msg_level ) + { + (zmerr->pub.format_message)( cinfo, buffer ); + Debug( msg_level, "%s", buffer ); + } + } } /* Expanded data destination object for memory */ typedef struct { - struct jpeg_destination_mgr pub; /* public fields */ + struct jpeg_destination_mgr pub; /* public fields */ - JOCTET *outbuffer; /* target buffer */ - int *outbuffer_size; - JOCTET *buffer; /* start of buffer */ + JOCTET *outbuffer; /* target buffer */ + int *outbuffer_size; + JOCTET *buffer; /* start of buffer */ } mem_destination_mgr; typedef mem_destination_mgr * mem_dest_ptr; -#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ /* * Initialize destination --- called by jpeg_start_compress @@ -99,15 +99,15 @@ typedef mem_destination_mgr * mem_dest_ptr; static void init_destination (j_compress_ptr cinfo) { - mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - /* Allocate the output buffer --- it will be released when done with image */ - dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - *(dest->outbuffer_size) = 0; + *(dest->outbuffer_size) = 0; } @@ -136,15 +136,15 @@ static void init_destination (j_compress_ptr cinfo) static boolean empty_output_buffer (j_compress_ptr cinfo) { - mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, OUTPUT_BUF_SIZE ); - *(dest->outbuffer_size) += OUTPUT_BUF_SIZE; + memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, OUTPUT_BUF_SIZE ); + *(dest->outbuffer_size) += OUTPUT_BUF_SIZE; - dest->pub.next_output_byte = dest->buffer; - dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; - return( TRUE ); + return( TRUE ); } /* @@ -158,14 +158,14 @@ static boolean empty_output_buffer (j_compress_ptr cinfo) static void term_destination (j_compress_ptr cinfo) { - mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; - size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; - if ( datacount > 0 ) - { - memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, datacount ); - *(dest->outbuffer_size) += datacount; - } + if ( datacount > 0 ) + { + memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, datacount ); + *(dest->outbuffer_size) += datacount; + } } @@ -177,45 +177,45 @@ static void term_destination (j_compress_ptr cinfo) void zm_jpeg_mem_dest (j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size ) { - mem_dest_ptr dest; + mem_dest_ptr dest; - /* The destination object is made permanent so that multiple JPEG images - * can be written to the same file without re-executing jpeg_stdio_dest. - * This makes it dangerous to use this manager and a different destination - * manager serially with the same JPEG object, because their private object - * sizes may be different. Caveat programmer. - */ - if ( cinfo->dest == NULL ) - { - /* first time for this JPEG object? */ - cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(mem_destination_mgr)); - } + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if ( cinfo->dest == NULL ) + { + /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(mem_destination_mgr)); + } - dest = (mem_dest_ptr) cinfo->dest; - dest->pub.init_destination = init_destination; - dest->pub.empty_output_buffer = empty_output_buffer; - dest->pub.term_destination = term_destination; - dest->outbuffer = outbuffer; - dest->outbuffer_size = outbuffer_size; + dest = (mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outbuffer = outbuffer; + dest->outbuffer_size = outbuffer_size; } /* Expanded data source object for memory input */ typedef struct { - struct jpeg_source_mgr pub; /* public fields */ + struct jpeg_source_mgr pub; /* public fields */ - JOCTET * inbuffer; /* source stream */ - int inbuffer_size; - int inbuffer_size_hwm; /* High water mark */ + JOCTET * inbuffer; /* source stream */ + int inbuffer_size; + int inbuffer_size_hwm; /* High water mark */ - JOCTET * buffer; /* start of buffer */ - boolean start_of_data; /* have we gotten any data yet? */ + JOCTET * buffer; /* start of buffer */ + boolean start_of_data; /* have we gotten any data yet? */ } mem_source_mgr; typedef mem_source_mgr * mem_src_ptr; -#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ /* * Initialize source --- called by jpeg_read_header @@ -224,14 +224,14 @@ typedef mem_source_mgr * mem_src_ptr; static void init_source (j_decompress_ptr cinfo) { - mem_src_ptr src = (mem_src_ptr) cinfo->src; + mem_src_ptr src = (mem_src_ptr) cinfo->src; - /* We reset the empty-input-file flag for each image, - * but we don't clear the input buffer. - * This is correct behavior for reading a series of images from one source. - */ - src->start_of_data = TRUE; - src->pub.bytes_in_buffer = 0; + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_data = TRUE; + src->pub.bytes_in_buffer = 0; } @@ -270,26 +270,26 @@ static void init_source (j_decompress_ptr cinfo) static boolean fill_input_buffer (j_decompress_ptr cinfo) { - mem_src_ptr src = (mem_src_ptr) cinfo->src; - size_t nbytes; + mem_src_ptr src = (mem_src_ptr) cinfo->src; + size_t nbytes; - memcpy( src->buffer, src->inbuffer, (size_t) src->inbuffer_size ); - nbytes = src->inbuffer_size; + memcpy( src->buffer, src->inbuffer, (size_t) src->inbuffer_size ); + nbytes = src->inbuffer_size; - if ( nbytes <= 0 ) - { - if ( src->start_of_data ) /* Treat empty input file as fatal error */ - ERREXIT(cinfo, JERR_INPUT_EMPTY); - WARNMS(cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - src->buffer[0] = (JOCTET) 0xFF; - src->buffer[1] = (JOCTET) JPEG_EOI; - nbytes = 2; - } + if ( nbytes <= 0 ) + { + if ( src->start_of_data ) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } - src->pub.next_input_byte = src->buffer; - src->pub.bytes_in_buffer = nbytes; - src->start_of_data = FALSE; + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_data = FALSE; return( TRUE ); } @@ -309,25 +309,25 @@ static boolean fill_input_buffer (j_decompress_ptr cinfo) static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { - mem_src_ptr src = (mem_src_ptr) cinfo->src; + mem_src_ptr src = (mem_src_ptr) cinfo->src; - /* Just a dumb implementation for now. Could use fseek() except - * it doesn't work on pipes. Not clear that being smart is worth - * any trouble anyway --- large skips are infrequent. - */ - if ( num_bytes > 0 ) + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if ( num_bytes > 0 ) + { + while ( num_bytes > (long) src->pub.bytes_in_buffer ) { - while ( num_bytes > (long) src->pub.bytes_in_buffer ) - { - num_bytes -= (long) src->pub.bytes_in_buffer; - (void) fill_input_buffer(cinfo); - /* note we assume that fill_input_buffer will never return FALSE, - * so suspension need not be handled. - */ - } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } } @@ -342,7 +342,7 @@ static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) static void term_source (j_decompress_ptr cinfo) { - /* no work necessary here */ + /* no work necessary here */ } @@ -354,114 +354,114 @@ static void term_source (j_decompress_ptr cinfo) void zm_jpeg_mem_src( j_decompress_ptr cinfo, const JOCTET *inbuffer, int inbuffer_size ) { - mem_src_ptr src; - - /* The source object and input buffer are made permanent so that a series - * of JPEG images can be read from the same file by calling zm_jpeg_mem_src - * only before the first one. (If we discarded the buffer at the end of - * one image, we'd likely lose the start of the next one.) - * This makes it unsafe to use this manager and a different source - * manager serially with the same JPEG object. Caveat programmer. - */ - if ( cinfo->src == NULL ) - { - /* first time for this JPEG object? */ - cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(mem_source_mgr)); - src = (mem_src_ptr) cinfo->src; - src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, inbuffer_size * SIZEOF(JOCTET)); - src->inbuffer_size_hwm = inbuffer_size; - } - else - { - src = (mem_src_ptr) cinfo->src; - if ( src->inbuffer_size_hwm < inbuffer_size ) - { - src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, inbuffer_size * SIZEOF(JOCTET)); - src->inbuffer_size_hwm = inbuffer_size; - } - } + mem_src_ptr src; + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling zm_jpeg_mem_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if ( cinfo->src == NULL ) + { + /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(mem_source_mgr)); src = (mem_src_ptr) cinfo->src; - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ - src->pub.term_source = term_source; - src->inbuffer = (JOCTET *)inbuffer; - src->inbuffer_size = inbuffer_size; - src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ - src->pub.next_input_byte = NULL; /* until buffer loaded */ + src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, inbuffer_size * SIZEOF(JOCTET)); + src->inbuffer_size_hwm = inbuffer_size; + } + else + { + src = (mem_src_ptr) cinfo->src; + if ( src->inbuffer_size_hwm < inbuffer_size ) + { + src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, inbuffer_size * SIZEOF(JOCTET)); + src->inbuffer_size_hwm = inbuffer_size; + } + } + + src = (mem_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->inbuffer = (JOCTET *)inbuffer; + src->inbuffer_size = inbuffer_size; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ } void zm_use_std_huff_tables( j_decompress_ptr cinfo ) { - /* JPEG standard Huffman tables (cf. JPEG standard section K.3) */ - /* IMPORTANT: these are only valid for 8-bit data precision! */ - static const JHUFF_TBL dclumin = { - { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, - FALSE - }; - static const JHUFF_TBL dcchrome = { - { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, - FALSE - }; - static const JHUFF_TBL aclumin = { - { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }, - { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }, - FALSE - }; - static const JHUFF_TBL acchrome = { - { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }, - { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa }, - FALSE - }; - - cinfo->dc_huff_tbl_ptrs[0] = (JHUFF_TBL*)&dclumin; - cinfo->dc_huff_tbl_ptrs[1] = (JHUFF_TBL*)&dcchrome; - cinfo->ac_huff_tbl_ptrs[0] = (JHUFF_TBL*)&aclumin; - cinfo->ac_huff_tbl_ptrs[1] = (JHUFF_TBL*)&acchrome; - + /* JPEG standard Huffman tables (cf. JPEG standard section K.3) */ + /* IMPORTANT: these are only valid for 8-bit data precision! */ + static const JHUFF_TBL dclumin = { + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + FALSE + }; + static const JHUFF_TBL dcchrome = { + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + FALSE + }; + static const JHUFF_TBL aclumin = { + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }, + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }, + FALSE + }; + static const JHUFF_TBL acchrome = { + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }, + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }, + FALSE + }; + + cinfo->dc_huff_tbl_ptrs[0] = (JHUFF_TBL*)&dclumin; + cinfo->dc_huff_tbl_ptrs[1] = (JHUFF_TBL*)&dcchrome; + cinfo->ac_huff_tbl_ptrs[0] = (JHUFF_TBL*)&aclumin; + cinfo->ac_huff_tbl_ptrs[1] = (JHUFF_TBL*)&acchrome; + } } diff --git a/src/zm_jpeg.h b/src/zm_jpeg.h index 94290869a..b7807d0d3 100644 --- a/src/zm_jpeg.h +++ b/src/zm_jpeg.h @@ -32,8 +32,8 @@ extern "C" /* Stuff for overriden error handlers */ struct zm_error_mgr { - struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; }; typedef struct zm_error_mgr *zm_error_ptr; diff --git a/src/zm_libvlc_camera.cpp b/src/zm_libvlc_camera.cpp index bfbcaa47d..26c4701fb 100644 --- a/src/zm_libvlc_camera.cpp +++ b/src/zm_libvlc_camera.cpp @@ -25,102 +25,102 @@ // Do all the buffer checking work here to avoid unnecessary locking void* LibvlcLockBuffer(void* opaque, void** planes) { - LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; - data->mutex.lock(); - - uint8_t* buffer = data->buffer; - data->buffer = data->prevBuffer; - data->prevBuffer = buffer; - - *planes = data->buffer; - return NULL; + LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; + data->mutex.lock(); + + uint8_t* buffer = data->buffer; + data->buffer = data->prevBuffer; + data->prevBuffer = buffer; + + *planes = data->buffer; + return NULL; } void LibvlcUnlockBuffer(void* opaque, void* picture, void *const *planes) { - LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; - - bool newFrame = false; - for(uint32_t i = 0; i < data->bufferSize; i++) + LibvlcPrivateData* data = (LibvlcPrivateData*)opaque; + + bool newFrame = false; + for(uint32_t i = 0; i < data->bufferSize; i++) + { + if(data->buffer[i] != data->prevBuffer[i]) { - if(data->buffer[i] != data->prevBuffer[i]) - { - newFrame = true; - break; - } - } - data->mutex.unlock(); - - time_t now; - time(&now); - // Return frames slightly faster than 1fps (if time() supports greater than one second resolution) - if(newFrame || difftime(now, data->prevTime) >= 0.8) - { - data->prevTime = now; - data->newImage.updateValueSignal(true); + newFrame = true; + break; } + } + data->mutex.unlock(); + + time_t now; + time(&now); + // Return frames slightly faster than 1fps (if time() supports greater than one second resolution) + if(newFrame || difftime(now, data->prevTime) >= 0.8) + { + data->prevTime = now; + data->newImage.updateValueSignal(true); + } } LibvlcCamera::LibvlcCamera( int p_id, const std::string &p_path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - Camera( p_id, LIBVLC_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), - mPath( p_path ), - mMethod( p_method ), - mOptions( p_options ) -{ - mLibvlcInstance = NULL; - mLibvlcMedia = NULL; - mLibvlcMediaPlayer = NULL; - mLibvlcData.buffer = NULL; - mLibvlcData.prevBuffer = NULL; + Camera( p_id, LIBVLC_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + mPath( p_path ), + mMethod( p_method ), + mOptions( p_options ) +{ + mLibvlcInstance = NULL; + mLibvlcMedia = NULL; + mLibvlcMediaPlayer = NULL; + mLibvlcData.buffer = NULL; + mLibvlcData.prevBuffer = NULL; - /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ - if(colours == ZM_COLOUR_RGB32) { - subpixelorder = ZM_SUBPIX_ORDER_BGRA; - mTargetChroma = "RV32"; - mBpp = 4; - } else if(colours == ZM_COLOUR_RGB24) { - subpixelorder = ZM_SUBPIX_ORDER_BGR; - mTargetChroma = "RV24"; - mBpp = 3; - } else if(colours == ZM_COLOUR_GRAY8) { - subpixelorder = ZM_SUBPIX_ORDER_NONE; - mTargetChroma = "GREY"; - mBpp = 1; - } else { - Panic("Unexpected colours: %d",colours); - } - - if ( capture ) - { - Initialise(); - } + /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + mTargetChroma = "RV32"; + mBpp = 4; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_BGR; + mTargetChroma = "RV24"; + mBpp = 3; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + mTargetChroma = "GREY"; + mBpp = 1; + } else { + Panic("Unexpected colours: %d",colours); + } + + if ( capture ) + { + Initialise(); + } } LibvlcCamera::~LibvlcCamera() { - if ( capture ) - { - Terminate(); - } - if(mLibvlcMediaPlayer != NULL) - { - libvlc_media_player_release(mLibvlcMediaPlayer); - mLibvlcMediaPlayer = NULL; - } - if(mLibvlcMedia != NULL) - { - libvlc_media_release(mLibvlcMedia); - mLibvlcMedia = NULL; - } - if(mLibvlcInstance != NULL) - { - libvlc_release(mLibvlcInstance); - mLibvlcInstance = NULL; - } - if (mOptArgV != NULL) - { - delete[] mOptArgV; - } + if ( capture ) + { + Terminate(); + } + if(mLibvlcMediaPlayer != NULL) + { + libvlc_media_player_release(mLibvlcMediaPlayer); + mLibvlcMediaPlayer = NULL; + } + if(mLibvlcMedia != NULL) + { + libvlc_media_release(mLibvlcMedia); + mLibvlcMedia = NULL; + } + if(mLibvlcInstance != NULL) + { + libvlc_release(mLibvlcInstance); + mLibvlcInstance = NULL; + } + if (mOptArgV != NULL) + { + delete[] mOptArgV; + } } void LibvlcCamera::Initialise() @@ -129,91 +129,91 @@ void LibvlcCamera::Initialise() void LibvlcCamera::Terminate() { - libvlc_media_player_stop(mLibvlcMediaPlayer); - if(mLibvlcData.buffer != NULL) - { - zm_freealigned(mLibvlcData.buffer); - } - if(mLibvlcData.prevBuffer != NULL) - { - zm_freealigned(mLibvlcData.prevBuffer); - } + libvlc_media_player_stop(mLibvlcMediaPlayer); + if(mLibvlcData.buffer != NULL) + { + zm_freealigned(mLibvlcData.buffer); + } + if(mLibvlcData.prevBuffer != NULL) + { + zm_freealigned(mLibvlcData.prevBuffer); + } } int LibvlcCamera::PrimeCapture() { - Info("Priming capture from %s", mPath.c_str()); - - StringVector opVect = split(Options(), ","); - - // Set transport method as specified by method field, rtpUni is default - if ( Method() == "rtpMulti" ) - opVect.push_back("--rtsp-mcast"); - else if ( Method() == "rtpRtsp" ) - opVect.push_back("--rtsp-tcp"); - else if ( Method() == "rtpRtspHttp" ) - opVect.push_back("--rtsp-http"); + Info("Priming capture from %s", mPath.c_str()); + + StringVector opVect = split(Options(), ","); + + // Set transport method as specified by method field, rtpUni is default + if ( Method() == "rtpMulti" ) + opVect.push_back("--rtsp-mcast"); + else if ( Method() == "rtpRtsp" ) + opVect.push_back("--rtsp-tcp"); + else if ( Method() == "rtpRtspHttp" ) + opVect.push_back("--rtsp-http"); - if (opVect.size() > 0) - { - mOptArgV = new char*[opVect.size()]; - Debug(2, "Number of Options: %d",opVect.size()); - for (size_t i=0; i< opVect.size(); i++) { - opVect[i] = trimSpaces(opVect[i]); - mOptArgV[i] = (char *)opVect[i].c_str(); - Debug(2, "set option %d to '%s'", i, opVect[i].c_str()); - } + if (opVect.size() > 0) + { + mOptArgV = new char*[opVect.size()]; + Debug(2, "Number of Options: %d",opVect.size()); + for (size_t i=0; i< opVect.size(); i++) { + opVect[i] = trimSpaces(opVect[i]); + mOptArgV[i] = (char *)opVect[i].c_str(); + Debug(2, "set option %d to '%s'", i, opVect[i].c_str()); } + } - mLibvlcInstance = libvlc_new (opVect.size(), (const char* const*)mOptArgV); - if(mLibvlcInstance == NULL) - Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg()); - - mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str()); - if(mLibvlcMedia == NULL) - Fatal("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg()); - - mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia); - if(mLibvlcMediaPlayer == NULL) - Fatal("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg()); + mLibvlcInstance = libvlc_new (opVect.size(), (const char* const*)mOptArgV); + if(mLibvlcInstance == NULL) + Fatal("Unable to create libvlc instance due to: %s", libvlc_errmsg()); + + mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str()); + if(mLibvlcMedia == NULL) + Fatal("Unable to open input %s due to: %s", mPath.c_str(), libvlc_errmsg()); + + mLibvlcMediaPlayer = libvlc_media_player_new_from_media(mLibvlcMedia); + if(mLibvlcMediaPlayer == NULL) + Fatal("Unable to create player for %s due to: %s", mPath.c_str(), libvlc_errmsg()); - libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp); - libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData); + libvlc_video_set_format(mLibvlcMediaPlayer, mTargetChroma.c_str(), width, height, width * mBpp); + libvlc_video_set_callbacks(mLibvlcMediaPlayer, &LibvlcLockBuffer, &LibvlcUnlockBuffer, NULL, &mLibvlcData); - mLibvlcData.bufferSize = width * height * mBpp; - // Libvlc wants 32 byte alignment for images (should in theory do this for all image lines) - mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize); - mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize); - - mLibvlcData.newImage.setValueImmediate(false); + mLibvlcData.bufferSize = width * height * mBpp; + // Libvlc wants 32 byte alignment for images (should in theory do this for all image lines) + mLibvlcData.buffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize); + mLibvlcData.prevBuffer = (uint8_t*)zm_mallocaligned(32, mLibvlcData.bufferSize); + + mLibvlcData.newImage.setValueImmediate(false); - libvlc_media_player_play(mLibvlcMediaPlayer); - - return(0); + libvlc_media_player_play(mLibvlcMediaPlayer); + + return(0); } int LibvlcCamera::PreCapture() -{ - return(0); +{ + return(0); } // Should not return -1 as cancels capture. Always wait for image if available. int LibvlcCamera::Capture( Image &image ) { - while(!mLibvlcData.newImage.getValueImmediate()) - mLibvlcData.newImage.getUpdatedValue(1); + while(!mLibvlcData.newImage.getValueImmediate()) + mLibvlcData.newImage.getUpdatedValue(1); - mLibvlcData.mutex.lock(); - image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp); - mLibvlcData.newImage.setValueImmediate(false); - mLibvlcData.mutex.unlock(); - - return (0); + mLibvlcData.mutex.lock(); + image.Assign(width, height, colours, subpixelorder, mLibvlcData.buffer, width * height * mBpp); + mLibvlcData.newImage.setValueImmediate(false); + mLibvlcData.mutex.unlock(); + + return (0); } int LibvlcCamera::PostCapture() { - return(0); + return(0); } #endif // HAVE_LIBVLC diff --git a/src/zm_libvlc_camera.h b/src/zm_libvlc_camera.h index 96414cb88..d08b310f5 100644 --- a/src/zm_libvlc_camera.h +++ b/src/zm_libvlc_camera.h @@ -33,44 +33,44 @@ // Used by libvlc callbacks struct LibvlcPrivateData { - uint8_t* buffer; - uint8_t* prevBuffer; - time_t prevTime; - uint32_t bufferSize; - Mutex mutex; - ThreadData newImage; + uint8_t* buffer; + uint8_t* prevBuffer; + time_t prevTime; + uint32_t bufferSize; + Mutex mutex; + ThreadData newImage; }; class LibvlcCamera : public Camera { protected: - std::string mPath; - std::string mMethod; - std::string mOptions; - char **mOptArgV; - LibvlcPrivateData mLibvlcData; - std::string mTargetChroma; - uint8_t mBpp; + std::string mPath; + std::string mMethod; + std::string mOptions; + char **mOptArgV; + LibvlcPrivateData mLibvlcData; + std::string mTargetChroma; + uint8_t mBpp; - libvlc_instance_t *mLibvlcInstance; - libvlc_media_t *mLibvlcMedia; - libvlc_media_player_t *mLibvlcMediaPlayer; + libvlc_instance_t *mLibvlcInstance; + libvlc_media_t *mLibvlcMedia; + libvlc_media_player_t *mLibvlcMediaPlayer; public: - LibvlcCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - ~LibvlcCamera(); + LibvlcCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~LibvlcCamera(); - const std::string &Path() const { return( mPath ); } - const std::string &Options() const { return( mOptions ); } - const std::string &Method() const { return( mMethod ); } + const std::string &Path() const { return( mPath ); } + const std::string &Options() const { return( mOptions ); } + const std::string &Method() const { return( mMethod ); } - void Initialise(); - void Terminate(); + void Initialise(); + void Terminate(); - int PrimeCapture(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); }; #endif // HAVE_LIBVLC diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 022f35dbe..6e1a21d6e 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -43,216 +43,216 @@ static unsigned int BigEndian; static int vidioctl( int fd, int request, void *arg ) { - int result = -1; - do - { - result = ioctl( fd, request, arg ); - } while ( result == -1 && errno == EINTR ); - return( result ); + int result = -1; + do + { + result = ioctl( fd, request, arg ); + } while ( result == -1 && errno == EINTR ); + return( result ); } #if HAVE_LIBSWSCALE static _AVPIXELFORMAT getFfPixFormatFromV4lPalette( int v4l_version, int palette ) { - _AVPIXELFORMAT pixFormat = AV_PIX_FMT_NONE; - + _AVPIXELFORMAT pixFormat = AV_PIX_FMT_NONE; + #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) + if ( v4l_version == 2 ) + { + switch( palette ) { - switch( palette ) - { #if defined(V4L2_PIX_FMT_RGB444) && defined(AV_PIX_FMT_RGB444) - case V4L2_PIX_FMT_RGB444 : - pixFormat = AV_PIX_FMT_RGB444; - break; + case V4L2_PIX_FMT_RGB444 : + pixFormat = AV_PIX_FMT_RGB444; + break; #endif // V4L2_PIX_FMT_RGB444 - case V4L2_PIX_FMT_RGB555 : - pixFormat = AV_PIX_FMT_RGB555; - break; - case V4L2_PIX_FMT_RGB565 : - pixFormat = AV_PIX_FMT_RGB565; - break; - case V4L2_PIX_FMT_BGR24 : - pixFormat = AV_PIX_FMT_BGR24; - break; - case V4L2_PIX_FMT_RGB24 : - pixFormat = AV_PIX_FMT_RGB24; - break; - case V4L2_PIX_FMT_BGR32 : - pixFormat = AV_PIX_FMT_BGRA; - break; - case V4L2_PIX_FMT_RGB32 : - pixFormat = AV_PIX_FMT_ARGB; - break; - case V4L2_PIX_FMT_GREY : - pixFormat = AV_PIX_FMT_GRAY8; - break; - case V4L2_PIX_FMT_YUYV : - pixFormat = AV_PIX_FMT_YUYV422; - break; - case V4L2_PIX_FMT_YUV422P : - pixFormat = AV_PIX_FMT_YUV422P; - break; - case V4L2_PIX_FMT_YUV411P : - pixFormat = AV_PIX_FMT_YUV411P; - break; + case V4L2_PIX_FMT_RGB555 : + pixFormat = AV_PIX_FMT_RGB555; + break; + case V4L2_PIX_FMT_RGB565 : + pixFormat = AV_PIX_FMT_RGB565; + break; + case V4L2_PIX_FMT_BGR24 : + pixFormat = AV_PIX_FMT_BGR24; + break; + case V4L2_PIX_FMT_RGB24 : + pixFormat = AV_PIX_FMT_RGB24; + break; + case V4L2_PIX_FMT_BGR32 : + pixFormat = AV_PIX_FMT_BGRA; + break; + case V4L2_PIX_FMT_RGB32 : + pixFormat = AV_PIX_FMT_ARGB; + break; + case V4L2_PIX_FMT_GREY : + pixFormat = AV_PIX_FMT_GRAY8; + break; + case V4L2_PIX_FMT_YUYV : + pixFormat = AV_PIX_FMT_YUYV422; + break; + case V4L2_PIX_FMT_YUV422P : + pixFormat = AV_PIX_FMT_YUV422P; + break; + case V4L2_PIX_FMT_YUV411P : + pixFormat = AV_PIX_FMT_YUV411P; + break; #ifdef V4L2_PIX_FMT_YUV444 - case V4L2_PIX_FMT_YUV444 : - pixFormat = AV_PIX_FMT_YUV444P; - break; + case V4L2_PIX_FMT_YUV444 : + pixFormat = AV_PIX_FMT_YUV444P; + break; #endif // V4L2_PIX_FMT_YUV444 - case V4L2_PIX_FMT_YUV410 : - pixFormat = AV_PIX_FMT_YUV410P; - break; - case V4L2_PIX_FMT_YUV420 : - pixFormat = AV_PIX_FMT_YUV420P; - break; - case V4L2_PIX_FMT_JPEG : - case V4L2_PIX_FMT_MJPEG : - pixFormat = AV_PIX_FMT_YUVJ444P; - break; - case V4L2_PIX_FMT_UYVY : - pixFormat = AV_PIX_FMT_UYVY422; - break; - // These don't seem to have ffmpeg equivalents - // See if you can match any of the ones in the default clause below!? - case V4L2_PIX_FMT_RGB332 : - case V4L2_PIX_FMT_RGB555X : - case V4L2_PIX_FMT_RGB565X : - //case V4L2_PIX_FMT_Y16 : - //case V4L2_PIX_FMT_PAL8 : - case V4L2_PIX_FMT_YVU410 : - case V4L2_PIX_FMT_YVU420 : - case V4L2_PIX_FMT_Y41P : - //case V4L2_PIX_FMT_YUV555 : - //case V4L2_PIX_FMT_YUV565 : - //case V4L2_PIX_FMT_YUV32 : - case V4L2_PIX_FMT_NV12 : - case V4L2_PIX_FMT_NV21 : - case V4L2_PIX_FMT_YYUV : - case V4L2_PIX_FMT_HI240 : - case V4L2_PIX_FMT_HM12 : - //case V4L2_PIX_FMT_SBGGR8 : - //case V4L2_PIX_FMT_SGBRG8 : - //case V4L2_PIX_FMT_SBGGR16 : - case V4L2_PIX_FMT_DV : - case V4L2_PIX_FMT_MPEG : - case V4L2_PIX_FMT_WNVA : - case V4L2_PIX_FMT_SN9C10X : - case V4L2_PIX_FMT_PWC1 : - case V4L2_PIX_FMT_PWC2 : - case V4L2_PIX_FMT_ET61X251 : - //case V4L2_PIX_FMT_SPCA501 : - //case V4L2_PIX_FMT_SPCA505 : - //case V4L2_PIX_FMT_SPCA508 : - //case V4L2_PIX_FMT_SPCA561 : - //case V4L2_PIX_FMT_PAC207 : - //case V4L2_PIX_FMT_PJPG : - //case V4L2_PIX_FMT_YVYU : - default : - { - Fatal( "Can't find swscale format for palette %d", palette ); - break; - // These are all spare and may match some of the above - pixFormat = AV_PIX_FMT_YUVJ420P; - pixFormat = AV_PIX_FMT_YUVJ422P; - pixFormat = AV_PIX_FMT_UYVY422; - pixFormat = AV_PIX_FMT_UYYVYY411; - pixFormat = AV_PIX_FMT_BGR565; - pixFormat = AV_PIX_FMT_BGR555; - pixFormat = AV_PIX_FMT_BGR8; - pixFormat = AV_PIX_FMT_BGR4; - pixFormat = AV_PIX_FMT_BGR4_BYTE; - pixFormat = AV_PIX_FMT_RGB8; - pixFormat = AV_PIX_FMT_RGB4; - pixFormat = AV_PIX_FMT_RGB4_BYTE; - pixFormat = AV_PIX_FMT_NV12; - pixFormat = AV_PIX_FMT_NV21; - pixFormat = AV_PIX_FMT_RGB32_1; - pixFormat = AV_PIX_FMT_BGR32_1; - pixFormat = AV_PIX_FMT_GRAY16BE; - pixFormat = AV_PIX_FMT_GRAY16LE; - pixFormat = AV_PIX_FMT_YUV440P; - pixFormat = AV_PIX_FMT_YUVJ440P; - pixFormat = AV_PIX_FMT_YUVA420P; - //pixFormat = AV_PIX_FMT_VDPAU_H264; - //pixFormat = AV_PIX_FMT_VDPAU_MPEG1; - //pixFormat = AV_PIX_FMT_VDPAU_MPEG2; - } - } + case V4L2_PIX_FMT_YUV410 : + pixFormat = AV_PIX_FMT_YUV410P; + break; + case V4L2_PIX_FMT_YUV420 : + pixFormat = AV_PIX_FMT_YUV420P; + break; + case V4L2_PIX_FMT_JPEG : + case V4L2_PIX_FMT_MJPEG : + pixFormat = AV_PIX_FMT_YUVJ444P; + break; + case V4L2_PIX_FMT_UYVY : + pixFormat = AV_PIX_FMT_UYVY422; + break; + // These don't seem to have ffmpeg equivalents + // See if you can match any of the ones in the default clause below!? + case V4L2_PIX_FMT_RGB332 : + case V4L2_PIX_FMT_RGB555X : + case V4L2_PIX_FMT_RGB565X : + //case V4L2_PIX_FMT_Y16 : + //case V4L2_PIX_FMT_PAL8 : + case V4L2_PIX_FMT_YVU410 : + case V4L2_PIX_FMT_YVU420 : + case V4L2_PIX_FMT_Y41P : + //case V4L2_PIX_FMT_YUV555 : + //case V4L2_PIX_FMT_YUV565 : + //case V4L2_PIX_FMT_YUV32 : + case V4L2_PIX_FMT_NV12 : + case V4L2_PIX_FMT_NV21 : + case V4L2_PIX_FMT_YYUV : + case V4L2_PIX_FMT_HI240 : + case V4L2_PIX_FMT_HM12 : + //case V4L2_PIX_FMT_SBGGR8 : + //case V4L2_PIX_FMT_SGBRG8 : + //case V4L2_PIX_FMT_SBGGR16 : + case V4L2_PIX_FMT_DV : + case V4L2_PIX_FMT_MPEG : + case V4L2_PIX_FMT_WNVA : + case V4L2_PIX_FMT_SN9C10X : + case V4L2_PIX_FMT_PWC1 : + case V4L2_PIX_FMT_PWC2 : + case V4L2_PIX_FMT_ET61X251 : + //case V4L2_PIX_FMT_SPCA501 : + //case V4L2_PIX_FMT_SPCA505 : + //case V4L2_PIX_FMT_SPCA508 : + //case V4L2_PIX_FMT_SPCA561 : + //case V4L2_PIX_FMT_PAC207 : + //case V4L2_PIX_FMT_PJPG : + //case V4L2_PIX_FMT_YVYU : + default : + { + Fatal( "Can't find swscale format for palette %d", palette ); + break; + // These are all spare and may match some of the above + pixFormat = AV_PIX_FMT_YUVJ420P; + pixFormat = AV_PIX_FMT_YUVJ422P; + pixFormat = AV_PIX_FMT_UYVY422; + pixFormat = AV_PIX_FMT_UYYVYY411; + pixFormat = AV_PIX_FMT_BGR565; + pixFormat = AV_PIX_FMT_BGR555; + pixFormat = AV_PIX_FMT_BGR8; + pixFormat = AV_PIX_FMT_BGR4; + pixFormat = AV_PIX_FMT_BGR4_BYTE; + pixFormat = AV_PIX_FMT_RGB8; + pixFormat = AV_PIX_FMT_RGB4; + pixFormat = AV_PIX_FMT_RGB4_BYTE; + pixFormat = AV_PIX_FMT_NV12; + pixFormat = AV_PIX_FMT_NV21; + pixFormat = AV_PIX_FMT_RGB32_1; + pixFormat = AV_PIX_FMT_BGR32_1; + pixFormat = AV_PIX_FMT_GRAY16BE; + pixFormat = AV_PIX_FMT_GRAY16LE; + pixFormat = AV_PIX_FMT_YUV440P; + pixFormat = AV_PIX_FMT_YUVJ440P; + pixFormat = AV_PIX_FMT_YUVA420P; + //pixFormat = AV_PIX_FMT_VDPAU_H264; + //pixFormat = AV_PIX_FMT_VDPAU_MPEG1; + //pixFormat = AV_PIX_FMT_VDPAU_MPEG2; + } } + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + switch( palette ) { - switch( palette ) - { - case VIDEO_PALETTE_RGB32 : - if(BigEndian) - pixFormat = AV_PIX_FMT_ARGB; - else - pixFormat = AV_PIX_FMT_BGRA; - break; - case VIDEO_PALETTE_RGB24 : - if(BigEndian) - pixFormat = AV_PIX_FMT_RGB24; - else - pixFormat = AV_PIX_FMT_BGR24; - break; - case VIDEO_PALETTE_GREY : - pixFormat = AV_PIX_FMT_GRAY8; - break; - case VIDEO_PALETTE_RGB555 : - pixFormat = AV_PIX_FMT_RGB555; - break; - case VIDEO_PALETTE_RGB565 : - pixFormat = AV_PIX_FMT_RGB565; - break; - case VIDEO_PALETTE_YUYV : - case VIDEO_PALETTE_YUV422 : - pixFormat = AV_PIX_FMT_YUYV422; - break; - case VIDEO_PALETTE_YUV422P : - pixFormat = AV_PIX_FMT_YUV422P; - break; - case VIDEO_PALETTE_YUV420P : - pixFormat = AV_PIX_FMT_YUV420P; - break; - default : - { - Fatal( "Can't find swscale format for palette %d", palette ); - break; - // These are all spare and may match some of the above - pixFormat = AV_PIX_FMT_YUVJ420P; - pixFormat = AV_PIX_FMT_YUVJ422P; - pixFormat = AV_PIX_FMT_YUVJ444P; - pixFormat = AV_PIX_FMT_UYVY422; - pixFormat = AV_PIX_FMT_UYYVYY411; - pixFormat = AV_PIX_FMT_BGR565; - pixFormat = AV_PIX_FMT_BGR555; - pixFormat = AV_PIX_FMT_BGR8; - pixFormat = AV_PIX_FMT_BGR4; - pixFormat = AV_PIX_FMT_BGR4_BYTE; - pixFormat = AV_PIX_FMT_RGB8; - pixFormat = AV_PIX_FMT_RGB4; - pixFormat = AV_PIX_FMT_RGB4_BYTE; - pixFormat = AV_PIX_FMT_NV12; - pixFormat = AV_PIX_FMT_NV21; - pixFormat = AV_PIX_FMT_RGB32_1; - pixFormat = AV_PIX_FMT_BGR32_1; - pixFormat = AV_PIX_FMT_GRAY16BE; - pixFormat = AV_PIX_FMT_GRAY16LE; - pixFormat = AV_PIX_FMT_YUV440P; - pixFormat = AV_PIX_FMT_YUVJ440P; - pixFormat = AV_PIX_FMT_YUVA420P; - //pixFormat = AV_PIX_FMT_VDPAU_H264; - //pixFormat = AV_PIX_FMT_VDPAU_MPEG1; - //pixFormat = AV_PIX_FMT_VDPAU_MPEG2; - } - } + case VIDEO_PALETTE_RGB32 : + if(BigEndian) + pixFormat = AV_PIX_FMT_ARGB; + else + pixFormat = AV_PIX_FMT_BGRA; + break; + case VIDEO_PALETTE_RGB24 : + if(BigEndian) + pixFormat = AV_PIX_FMT_RGB24; + else + pixFormat = AV_PIX_FMT_BGR24; + break; + case VIDEO_PALETTE_GREY : + pixFormat = AV_PIX_FMT_GRAY8; + break; + case VIDEO_PALETTE_RGB555 : + pixFormat = AV_PIX_FMT_RGB555; + break; + case VIDEO_PALETTE_RGB565 : + pixFormat = AV_PIX_FMT_RGB565; + break; + case VIDEO_PALETTE_YUYV : + case VIDEO_PALETTE_YUV422 : + pixFormat = AV_PIX_FMT_YUYV422; + break; + case VIDEO_PALETTE_YUV422P : + pixFormat = AV_PIX_FMT_YUV422P; + break; + case VIDEO_PALETTE_YUV420P : + pixFormat = AV_PIX_FMT_YUV420P; + break; + default : + { + Fatal( "Can't find swscale format for palette %d", palette ); + break; + // These are all spare and may match some of the above + pixFormat = AV_PIX_FMT_YUVJ420P; + pixFormat = AV_PIX_FMT_YUVJ422P; + pixFormat = AV_PIX_FMT_YUVJ444P; + pixFormat = AV_PIX_FMT_UYVY422; + pixFormat = AV_PIX_FMT_UYYVYY411; + pixFormat = AV_PIX_FMT_BGR565; + pixFormat = AV_PIX_FMT_BGR555; + pixFormat = AV_PIX_FMT_BGR8; + pixFormat = AV_PIX_FMT_BGR4; + pixFormat = AV_PIX_FMT_BGR4_BYTE; + pixFormat = AV_PIX_FMT_RGB8; + pixFormat = AV_PIX_FMT_RGB4; + pixFormat = AV_PIX_FMT_RGB4_BYTE; + pixFormat = AV_PIX_FMT_NV12; + pixFormat = AV_PIX_FMT_NV21; + pixFormat = AV_PIX_FMT_RGB32_1; + pixFormat = AV_PIX_FMT_BGR32_1; + pixFormat = AV_PIX_FMT_GRAY16BE; + pixFormat = AV_PIX_FMT_GRAY16LE; + pixFormat = AV_PIX_FMT_YUV440P; + pixFormat = AV_PIX_FMT_YUVJ440P; + pixFormat = AV_PIX_FMT_YUVA420P; + //pixFormat = AV_PIX_FMT_VDPAU_H264; + //pixFormat = AV_PIX_FMT_VDPAU_MPEG1; + //pixFormat = AV_PIX_FMT_VDPAU_MPEG2; + } } + } #endif // ZM_HAS_V4L1 - return( pixFormat ); + return( pixFormat ); } #endif // HAVE_LIBSWSCALE @@ -287,1935 +287,1935 @@ AVFrame **LocalCamera::capturePictures = 0; LocalCamera *LocalCamera::last_camera = NULL; LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel, int p_standard, bool p_v4l_multi_buffer, unsigned int p_v4l_captures_per_frame, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras) : - Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), - device( p_device ), - channel( p_channel ), - standard( p_standard ), - palette( p_palette ), - channel_index( 0 ), - extras ( p_extras ) + Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + device( p_device ), + channel( p_channel ), + standard( p_standard ), + palette( p_palette ), + channel_index( 0 ), + extras ( p_extras ) { - // If we are the first, or only, input on this device then - // do the initial opening etc - device_prime = (camera_count++ == 0); - v4l_version = (p_method=="v4l2"?2:1); - v4l_multi_buffer = p_v4l_multi_buffer; - v4l_captures_per_frame = p_v4l_captures_per_frame; - - if ( capture ) + // If we are the first, or only, input on this device then + // do the initial opening etc + device_prime = (camera_count++ == 0); + v4l_version = (p_method=="v4l2"?2:1); + v4l_multi_buffer = p_v4l_multi_buffer; + v4l_captures_per_frame = p_v4l_captures_per_frame; + + if ( capture ) + { + if ( device_prime ) { - if ( device_prime ) - { - Debug( 2, "V4L support enabled, using V4L%d api", v4l_version ); - } + Debug( 2, "V4L support enabled, using V4L%d api", v4l_version ); + } - if ( !last_camera || channel != last_camera->channel ) - { - // We are the first, or only, input that uses this channel - channel_prime = true; - channel_index = channel_count++; - channels[channel_index] = channel; - standards[channel_index] = standard; - } - else - { - // We are the second, or subsequent, input using this channel - channel_prime = false; - } - + if ( !last_camera || channel != last_camera->channel ) + { + // We are the first, or only, input that uses this channel + channel_prime = true; + channel_index = channel_count++; + channels[channel_index] = channel; + standards[channel_index] = standard; + } + else + { + // We are the second, or subsequent, input using this channel + channel_prime = false; } - /* The V4L1 API doesn't care about endianness, we need to check the endianness of the machine */ - uint32_t checkval = 0xAABBCCDD; - if(*(unsigned char*)&checkval == 0xDD) { - BigEndian = 0; - Debug(2,"little-endian processor detected"); - } else if(*(unsigned char*)&checkval == 0xAA) { - BigEndian = 1; - Debug(2,"Big-endian processor detected"); - } else { - Error("Unable to detect the processor's endianness. Assuming little-endian."); - BigEndian = 0; - } - + } + + /* The V4L1 API doesn't care about endianness, we need to check the endianness of the machine */ + uint32_t checkval = 0xAABBCCDD; + if(*(unsigned char*)&checkval == 0xDD) { + BigEndian = 0; + Debug(2,"little-endian processor detected"); + } else if(*(unsigned char*)&checkval == 0xAA) { + BigEndian = 1; + Debug(2,"Big-endian processor detected"); + } else { + Error("Unable to detect the processor's endianness. Assuming little-endian."); + BigEndian = 0; + } + #if ZM_HAS_V4L2 - if( v4l_version == 2 && palette == 0 ) { - /* Use automatic format selection */ - Debug(2,"Using automatic format selection"); - palette = AutoSelectFormat(colours); - if(palette == 0) { - Error("Automatic format selection failed. Falling back to YUYV"); - palette = V4L2_PIX_FMT_YUYV; - } else { - if(capture) { - Info("Selected capture palette: %s (%c%c%c%c)", palette_desc, palette&0xff, (palette>>8)&0xff, (palette>>16)&0xff, (palette>>24)&0xff); - } - } - } + if( v4l_version == 2 && palette == 0 ) { + /* Use automatic format selection */ + Debug(2,"Using automatic format selection"); + palette = AutoSelectFormat(colours); + if(palette == 0) { + Error("Automatic format selection failed. Falling back to YUYV"); + palette = V4L2_PIX_FMT_YUYV; + } else { + if(capture) { + Info("Selected capture palette: %s (%c%c%c%c)", palette_desc, palette&0xff, (palette>>8)&0xff, (palette>>16)&0xff, (palette>>24)&0xff); + } + } + } #endif - - if( capture ) { - if ( last_camera ) { - if ( (p_method == "v4l2" && v4l_version != 2) || (p_method == "v4l1" && v4l_version != 1) ) - Fatal( "Different Video For Linux version used for monitors sharing same device" ); - - if ( standard != last_camera->standard ) - Warning( "Different video standards defined for monitors sharing same device, results may be unpredictable or completely wrong" ); - - if ( palette != last_camera->palette ) - Warning( "Different video palettes defined for monitors sharing same device, results may be unpredictable or completely wrong" ); - - if ( width != last_camera->width || height != last_camera->height ) - Warning( "Different capture sizes defined for monitors sharing same device, results may be unpredictable or completely wrong" ); - } - + + if( capture ) { + if ( last_camera ) { + if ( (p_method == "v4l2" && v4l_version != 2) || (p_method == "v4l1" && v4l_version != 1) ) + Fatal( "Different Video For Linux version used for monitors sharing same device" ); + + if ( standard != last_camera->standard ) + Warning( "Different video standards defined for monitors sharing same device, results may be unpredictable or completely wrong" ); + + if ( palette != last_camera->palette ) + Warning( "Different video palettes defined for monitors sharing same device, results may be unpredictable or completely wrong" ); + + if ( width != last_camera->width || height != last_camera->height ) + Warning( "Different capture sizes defined for monitors sharing same device, results may be unpredictable or completely wrong" ); + } + #if HAVE_LIBSWSCALE - /* Get ffmpeg pixel format based on capture palette and endianness */ - capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette ); - imagePixFormat = AV_PIX_FMT_NONE; + /* Get ffmpeg pixel format based on capture palette and endianness */ + capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette ); + imagePixFormat = AV_PIX_FMT_NONE; #endif // HAVE_LIBSWSCALE - } + } - /* V4L2 format matching */ + /* V4L2 format matching */ #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) { - /* Try to find a match for the selected palette and target colourspace */ - - /* RGB32 palette and 32bit target colourspace */ - if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_ARGB; - - /* BGR32 palette and 32bit target colourspace */ - } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_BGRA; - - /* RGB24 palette and 24bit target colourspace */ - } else if(palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - - /* BGR24 palette and 24bit target colourspace */ - } else if(palette == V4L2_PIX_FMT_BGR24 && colours == ZM_COLOUR_RGB24) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_BGR; - - /* Grayscale palette and grayscale target colourspace */ - } else if(palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ - } else { - if( capture ) + if ( v4l_version == 2 ) { + /* Try to find a match for the selected palette and target colourspace */ + + /* RGB32 palette and 32bit target colourspace */ + if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_ARGB; + + /* BGR32 palette and 32bit target colourspace */ + } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + + /* RGB24 palette and 24bit target colourspace */ + } else if(palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + + /* BGR24 palette and 24bit target colourspace */ + } else if(palette == V4L2_PIX_FMT_BGR24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_BGR; + + /* Grayscale palette and grayscale target colourspace */ + } else if(palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ + } else { + if( capture ) #if HAVE_LIBSWSCALE - Info("No direct match for the selected palette (%c%c%c%c) and target colorspace (%d). Format conversion is required, performance penalty expected", (capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff), colours ); + Info("No direct match for the selected palette (%c%c%c%c) and target colorspace (%d). Format conversion is required, performance penalty expected", (capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff), colours ); #else - Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected"); + Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected"); #endif #if HAVE_LIBSWSCALE - /* Try using swscale for the conversion */ - conversion_type = 1; - Debug(2,"Using swscale for image conversion"); - if(colours == ZM_COLOUR_RGB32) { - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - imagePixFormat = AV_PIX_FMT_RGBA; - } else if(colours == ZM_COLOUR_RGB24) { - subpixelorder = ZM_SUBPIX_ORDER_RGB; - imagePixFormat = AV_PIX_FMT_RGB24; - } else if(colours == ZM_COLOUR_GRAY8) { - subpixelorder = ZM_SUBPIX_ORDER_NONE; - imagePixFormat = AV_PIX_FMT_GRAY8; - } else { - Panic("Unexpected colours: %d",colours); - } - if( capture ) { + /* Try using swscale for the conversion */ + conversion_type = 1; + Debug(2,"Using swscale for image conversion"); + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = AV_PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = AV_PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = AV_PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + if( capture ) { #if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0) - if(!sws_isSupportedInput(capturePixFormat)) { - Error("swscale does not support the used capture format: %c%c%c%c",(capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff)); - conversion_type = 2; /* Try ZM format conversions */ - } - if(!sws_isSupportedOutput(imagePixFormat)) { - Error("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); - conversion_type = 2; /* Try ZM format conversions */ - } + if(!sws_isSupportedInput(capturePixFormat)) { + Error("swscale does not support the used capture format: %c%c%c%c",(capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff)); + conversion_type = 2; /* Try ZM format conversions */ + } + if(!sws_isSupportedOutput(imagePixFormat)) { + Error("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); + conversion_type = 2; /* Try ZM format conversions */ + } #endif - } + } #else - /* Don't have swscale, see what we can do */ - conversion_type = 2; + /* Don't have swscale, see what we can do */ + conversion_type = 2; #endif - /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ - if(colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV) { - conversion_type = 2; - } - - /* JPEG */ - if(palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { - Debug(2,"Using JPEG image decoding"); - conversion_type = 3; - } - - if(conversion_type == 2) { - Debug(2,"Using ZM for image conversion"); - if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8) { - conversion_fptr = &std_convert_argb_gray8; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8) { - conversion_fptr = &std_convert_bgra_gray8; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8) { - /* Fast YUYV->Grayscale conversion by extracting the Y channel */ - if(config.cpu_extensions && sseversion >= 35) { - conversion_fptr = &ssse3_convert_yuyv_gray8; - Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); - } else { - conversion_fptr = &std_convert_yuyv_gray8; - Debug(2,"Using standard YUYV->grayscale fast conversion"); - } - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24) { - conversion_fptr = &zm_convert_yuyv_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32) { - conversion_fptr = &zm_convert_yuyv_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24) { - conversion_fptr = &zm_convert_rgb555_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32) { - conversion_fptr = &zm_convert_rgb555_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24) { - conversion_fptr = &zm_convert_rgb565_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32) { - conversion_fptr = &zm_convert_rgb565_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else { - Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); - } - } - } - } + /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ + if(colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV) { + conversion_type = 2; + } + + /* JPEG */ + if(palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { + Debug(2,"Using JPEG image decoding"); + conversion_type = 3; + } + + if(conversion_type == 2) { + Debug(2,"Using ZM for image conversion"); + if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8) { + conversion_fptr = &std_convert_argb_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8) { + conversion_fptr = &std_convert_bgra_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8) { + /* Fast YUYV->Grayscale conversion by extracting the Y channel */ + if(config.cpu_extensions && sseversion >= 35) { + conversion_fptr = &ssse3_convert_yuyv_gray8; + Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); + } else { + conversion_fptr = &std_convert_yuyv_gray8; + Debug(2,"Using standard YUYV->grayscale fast conversion"); + } + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_yuyv_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_yuyv_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb555_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb555_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb565_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb565_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else { + Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); + } + } + } + } #endif // ZM_HAS_V4L2 - /* V4L1 format matching */ + /* V4L1 format matching */ #if ZM_HAS_V4L1 - if ( v4l_version == 1) { - /* Try to find a match for the selected palette and target colourspace */ - - /* RGB32 palette and 32bit target colourspace */ - if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_RGB32) { - conversion_type = 0; - if(BigEndian) { - subpixelorder = ZM_SUBPIX_ORDER_ARGB; - } else { - subpixelorder = ZM_SUBPIX_ORDER_BGRA; - } - - /* RGB24 palette and 24bit target colourspace */ - } else if(palette == VIDEO_PALETTE_RGB24 && colours == ZM_COLOUR_RGB24) { - conversion_type = 0; - if(BigEndian) { - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else { - subpixelorder = ZM_SUBPIX_ORDER_BGR; - } - - /* Grayscale palette and grayscale target colourspace */ - } else if(palette == VIDEO_PALETTE_GREY && colours == ZM_COLOUR_GRAY8) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ - } else { - if( capture ) - Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected"); + if ( v4l_version == 1) { + /* Try to find a match for the selected palette and target colourspace */ + + /* RGB32 palette and 32bit target colourspace */ + if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + if(BigEndian) { + subpixelorder = ZM_SUBPIX_ORDER_ARGB; + } else { + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + } + + /* RGB24 palette and 24bit target colourspace */ + } else if(palette == VIDEO_PALETTE_RGB24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + if(BigEndian) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else { + subpixelorder = ZM_SUBPIX_ORDER_BGR; + } + + /* Grayscale palette and grayscale target colourspace */ + } else if(palette == VIDEO_PALETTE_GREY && colours == ZM_COLOUR_GRAY8) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ + } else { + if( capture ) + Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected"); #if HAVE_LIBSWSCALE - /* Try using swscale for the conversion */ - conversion_type = 1; - Debug(2,"Using swscale for image conversion"); - if(colours == ZM_COLOUR_RGB32) { - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - imagePixFormat = AV_PIX_FMT_RGBA; - } else if(colours == ZM_COLOUR_RGB24) { - subpixelorder = ZM_SUBPIX_ORDER_RGB; - imagePixFormat = AV_PIX_FMT_RGB24; - } else if(colours == ZM_COLOUR_GRAY8) { - subpixelorder = ZM_SUBPIX_ORDER_NONE; - imagePixFormat = AV_PIX_FMT_GRAY8; - } else { - Panic("Unexpected colours: %d",colours); - } - if( capture ) { - if(!sws_isSupportedInput(capturePixFormat)) { - Error("swscale does not support the used capture format"); - conversion_type = 2; /* Try ZM format conversions */ - } - if(!sws_isSupportedOutput(imagePixFormat)) { - Error("swscale does not support the target format"); - conversion_type = 2; /* Try ZM format conversions */ - } - } + /* Try using swscale for the conversion */ + conversion_type = 1; + Debug(2,"Using swscale for image conversion"); + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = AV_PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = AV_PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = AV_PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + if( capture ) { + if(!sws_isSupportedInput(capturePixFormat)) { + Error("swscale does not support the used capture format"); + conversion_type = 2; /* Try ZM format conversions */ + } + if(!sws_isSupportedOutput(imagePixFormat)) { + Error("swscale does not support the target format"); + conversion_type = 2; /* Try ZM format conversions */ + } + } #else - /* Don't have swscale, see what we can do */ - conversion_type = 2; + /* Don't have swscale, see what we can do */ + conversion_type = 2; #endif - /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ - if(colours == ZM_COLOUR_GRAY8 && (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422)) { - conversion_type = 2; - } - - if(conversion_type == 2) { - Debug(2,"Using ZM for image conversion"); - if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_GRAY8) { - if(BigEndian) { - conversion_fptr = &std_convert_argb_gray8; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else { - conversion_fptr = &std_convert_bgra_gray8; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } - } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8) { - /* Fast YUYV->Grayscale conversion by extracting the Y channel */ - if(config.cpu_extensions && sseversion >= 35) { - conversion_fptr = &ssse3_convert_yuyv_gray8; - Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); - } else { - conversion_fptr = &std_convert_yuyv_gray8; - Debug(2,"Using standard YUYV->grayscale fast conversion"); - } - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB24) { - conversion_fptr = &zm_convert_yuyv_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB32) { - conversion_fptr = &zm_convert_yuyv_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB24) { - conversion_fptr = &zm_convert_rgb555_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB32) { - conversion_fptr = &zm_convert_rgb555_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB24) { - conversion_fptr = &zm_convert_rgb565_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB32) { - conversion_fptr = &zm_convert_rgb565_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else { - Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); - } - } - } - } -#endif // ZM_HAS_V4L1 + /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ + if(colours == ZM_COLOUR_GRAY8 && (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422)) { + conversion_type = 2; + } + + if(conversion_type == 2) { + Debug(2,"Using ZM for image conversion"); + if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_GRAY8) { + if(BigEndian) { + conversion_fptr = &std_convert_argb_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else { + conversion_fptr = &std_convert_bgra_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } + } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8) { + /* Fast YUYV->Grayscale conversion by extracting the Y channel */ + if(config.cpu_extensions && sseversion >= 35) { + conversion_fptr = &ssse3_convert_yuyv_gray8; + Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); + } else { + conversion_fptr = &std_convert_yuyv_gray8; + Debug(2,"Using standard YUYV->grayscale fast conversion"); + } + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_yuyv_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_yuyv_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb555_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb555_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb565_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb565_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else { + Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); + } + } + } + } +#endif // ZM_HAS_V4L1 - last_camera = this; - Debug(3,"Selected subpixelorder: %d",subpixelorder); + last_camera = this; + Debug(3,"Selected subpixelorder: %d",subpixelorder); #if HAVE_LIBSWSCALE - /* Initialize swscale stuff */ - if(capture && conversion_type == 1) { + /* Initialize swscale stuff */ + if(capture && conversion_type == 1) { #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - tmpPicture = av_frame_alloc(); + tmpPicture = av_frame_alloc(); #else - tmpPicture = avcodec_alloc_frame(); + tmpPicture = avcodec_alloc_frame(); #endif - if ( !tmpPicture ) - Fatal( "Could not allocate temporary picture" ); - - int pSize = avpicture_get_size( imagePixFormat, width, height ); - if( (unsigned int)pSize != imagesize) { - Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); - } - - imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); - - if ( !imgConversionContext ) { - Fatal( "Unable to initialise image scaling context" ); - } - - } + if ( !tmpPicture ) + Fatal( "Could not allocate temporary picture" ); + + int pSize = avpicture_get_size( imagePixFormat, width, height ); + if( (unsigned int)pSize != imagesize) { + Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); + } + + imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); + + if ( !imgConversionContext ) { + Fatal( "Unable to initialise image scaling context" ); + } + + } #endif } LocalCamera::~LocalCamera() { - if ( device_prime && capture ) - Terminate(); - + if ( device_prime && capture ) + Terminate(); + #if HAVE_LIBSWSCALE - /* Clean up swscale stuff */ - if(capture && conversion_type == 1) { - sws_freeContext(imgConversionContext); - imgConversionContext = NULL; - + /* Clean up swscale stuff */ + if(capture && conversion_type == 1) { + sws_freeContext(imgConversionContext); + imgConversionContext = NULL; + #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &tmpPicture ); + av_frame_free( &tmpPicture ); #else - av_freep( &tmpPicture ); + av_freep( &tmpPicture ); #endif - } + } #endif } void LocalCamera::Initialise() { #if HAVE_LIBSWSCALE - if ( logDebugging() ) - av_log_set_level( AV_LOG_DEBUG ); - else - av_log_set_level( AV_LOG_QUIET ); + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); #endif // HAVE_LIBSWSCALE - struct stat st; + struct stat st; - if ( stat( device.c_str(), &st ) < 0 ) - Fatal( "Failed to stat video device %s: %s", device.c_str(), strerror(errno) ); + if ( stat( device.c_str(), &st ) < 0 ) + Fatal( "Failed to stat video device %s: %s", device.c_str(), strerror(errno) ); - if ( !S_ISCHR(st.st_mode) ) - Fatal( "File %s is not device file: %s", device.c_str(), strerror(errno) ); + if ( !S_ISCHR(st.st_mode) ) + Fatal( "File %s is not device file: %s", device.c_str(), strerror(errno) ); - Debug( 3, "Opening video device %s", device.c_str() ); - //if ( (vid_fd = open( device.c_str(), O_RDWR|O_NONBLOCK, 0 )) < 0 ) - if ( (vid_fd = open( device.c_str(), O_RDWR, 0 )) < 0 ) - Fatal( "Failed to open video device %s: %s", device.c_str(), strerror(errno) ); + Debug( 3, "Opening video device %s", device.c_str() ); + //if ( (vid_fd = open( device.c_str(), O_RDWR|O_NONBLOCK, 0 )) < 0 ) + if ( (vid_fd = open( device.c_str(), O_RDWR, 0 )) < 0 ) + Fatal( "Failed to open video device %s: %s", device.c_str(), strerror(errno) ); #if ZM_HAS_V4L2 - Debug( 2, "V4L2 support enabled, using V4L%d api", v4l_version ); - if ( v4l_version == 2 ) + Debug( 2, "V4L2 support enabled, using V4L%d api", v4l_version ); + if ( v4l_version == 2 ) + { + struct v4l2_capability vid_cap; + + Debug( 3, "Checking video device capabilities" ); + if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 ) + Fatal( "Failed to query video device: %s", strerror(errno) ); + + if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ) + Fatal( "Video device is not video capture device" ); + + if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) ) + Fatal( "Video device does not support streaming i/o" ); + + Debug( 3, "Setting up video format" ); + + memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) ); + v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 ) + Fatal( "Failed to get video format: %s", strerror(errno) ); + + Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); + Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width ); + Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height ); + Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat ); + Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field ); + Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline ); + Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage ); + Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace ); + Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv ); + + v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_data.fmt.fmt.pix.width = width; + v4l2_data.fmt.fmt.pix.height = height; + v4l2_data.fmt.fmt.pix.pixelformat = palette; + + if ( (extras & 0xff) != 0 ) + { + v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff); + + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { - struct v4l2_capability vid_cap; + Warning( "Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff) ); + v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { + Fatal( "Failed to set video format: %s", strerror(errno) ); + } + } + } else { + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { + Fatal( "Failed to set video format: %s", strerror(errno) ); + } + } - Debug( 3, "Checking video device capabilities" ); - if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 ) - Fatal( "Failed to query video device: %s", strerror(errno) ); + /* Note VIDIOC_S_FMT may change width and height. */ + Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); + Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width ); + Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height ); + Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat ); + Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field ); + Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline ); + Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage ); + Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace ); + Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv ); - if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ) - Fatal( "Video device is not video capture device" ); + /* Buggy driver paranoia. */ + unsigned int min; + min = v4l2_data.fmt.fmt.pix.width * 2; + if (v4l2_data.fmt.fmt.pix.bytesperline < min) + v4l2_data.fmt.fmt.pix.bytesperline = min; + min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height; + if (v4l2_data.fmt.fmt.pix.sizeimage < min) + v4l2_data.fmt.fmt.pix.sizeimage = min; - if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) ) - Fatal( "Video device does not support streaming i/o" ); - - Debug( 3, "Setting up video format" ); - - memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) ); - v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 ) - Fatal( "Failed to get video format: %s", strerror(errno) ); - - Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); - Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width ); - Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height ); - Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat ); - Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field ); - Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline ); - Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage ); - Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace ); - Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv ); - - v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_data.fmt.fmt.pix.width = width; - v4l2_data.fmt.fmt.pix.height = height; - v4l2_data.fmt.fmt.pix.pixelformat = palette; - - if ( (extras & 0xff) != 0 ) - { - v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff); - - if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) - { - Warning( "Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff) ); - v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; - if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { - Fatal( "Failed to set video format: %s", strerror(errno) ); - } - } - } else { - if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { - Fatal( "Failed to set video format: %s", strerror(errno) ); - } - } - - /* Note VIDIOC_S_FMT may change width and height. */ - Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); - Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width ); - Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height ); - Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat ); - Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field ); - Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline ); - Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage ); - Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace ); - Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv ); - - /* Buggy driver paranoia. */ - unsigned int min; - min = v4l2_data.fmt.fmt.pix.width * 2; - if (v4l2_data.fmt.fmt.pix.bytesperline < min) - v4l2_data.fmt.fmt.pix.bytesperline = min; - min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height; - if (v4l2_data.fmt.fmt.pix.sizeimage < min) - v4l2_data.fmt.fmt.pix.sizeimage = min; - - v4l2_jpegcompression jpeg_comp; - if(palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { - if( vidioctl( vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp ) < 0 ) { - if(errno == EINVAL) { - Debug(2, "JPEG compression options are not available"); - } else { - Warning("Failed to get JPEG compression options: %s", strerror(errno) ); - } - } else { - /* Set flags and quality. MJPEG should not have the huffman tables defined */ - if(palette == V4L2_PIX_FMT_MJPEG) { - jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; - } else { - jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT; - } - jpeg_comp.quality = 85; - - /* Update the JPEG options */ - if( vidioctl( vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp ) < 0 ) { - Warning("Failed to set JPEG compression options: %s", strerror(errno) ); - } else { - if(vidioctl( vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp ) < 0) { - Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno) ); - } else { - Debug(4, "JPEG quality: %d",jpeg_comp.quality); - Debug(4, "JPEG markers: %#x",jpeg_comp.jpeg_markers); - } - } - } - } - - Debug( 3, "Setting up request buffers" ); - - memset( &v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs) ); - if ( channel_count > 1 ) { - Debug( 3, "Channel count is %d", channel_count ); - if ( v4l_multi_buffer ){ - v4l2_data.reqbufs.count = 2*channel_count; - } else { - v4l2_data.reqbufs.count = 1; - } + v4l2_jpegcompression jpeg_comp; + if(palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { + if( vidioctl( vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp ) < 0 ) { + if(errno == EINVAL) { + Debug(2, "JPEG compression options are not available"); + } else { + Warning("Failed to get JPEG compression options: %s", strerror(errno) ); + } + } else { + /* Set flags and quality. MJPEG should not have the huffman tables defined */ + if(palette == V4L2_PIX_FMT_MJPEG) { + jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; + } else { + jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT; + } + jpeg_comp.quality = 85; + + /* Update the JPEG options */ + if( vidioctl( vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp ) < 0 ) { + Warning("Failed to set JPEG compression options: %s", strerror(errno) ); + } else { + if(vidioctl( vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp ) < 0) { + Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno) ); } else { - v4l2_data.reqbufs.count = 8; - } - Debug( 3, "Request buffers count is %d", v4l2_data.reqbufs.count ); - - v4l2_data.reqbufs.type = v4l2_data.fmt.type; - v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP; - - if ( vidioctl( vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs ) < 0 ) - { - if ( errno == EINVAL ) - { - Fatal( "Unable to initialise memory mapping, unsupported in device" ); - } - else - { - Fatal( "Unable to initialise memory mapping: %s", strerror(errno) ); - } + Debug(4, "JPEG quality: %d",jpeg_comp.quality); + Debug(4, "JPEG markers: %#x",jpeg_comp.jpeg_markers); } + } + } + } - if ( v4l2_data.reqbufs.count < (v4l_multi_buffer?2:1) ) - Fatal( "Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count ); + Debug( 3, "Setting up request buffers" ); + + memset( &v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs) ); + if ( channel_count > 1 ) { + Debug( 3, "Channel count is %d", channel_count ); + if ( v4l_multi_buffer ){ + v4l2_data.reqbufs.count = 2*channel_count; + } else { + v4l2_data.reqbufs.count = 1; + } + } else { + v4l2_data.reqbufs.count = 8; + } + Debug( 3, "Request buffers count is %d", v4l2_data.reqbufs.count ); - Debug( 3, "Setting up data buffers: Channels %d MultiBuffer %d Buffers: %d", channel_count, v4l_multi_buffer, v4l2_data.reqbufs.count ); + v4l2_data.reqbufs.type = v4l2_data.fmt.type; + v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP; - v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count]; + if ( vidioctl( vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs ) < 0 ) + { + if ( errno == EINVAL ) + { + Fatal( "Unable to initialise memory mapping, unsupported in device" ); + } + else + { + Fatal( "Unable to initialise memory mapping: %s", strerror(errno) ); + } + } + + if ( v4l2_data.reqbufs.count < (v4l_multi_buffer?2:1) ) + Fatal( "Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count ); + + Debug( 3, "Setting up data buffers: Channels %d MultiBuffer %d Buffers: %d", channel_count, v4l_multi_buffer, v4l2_data.reqbufs.count ); + + v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count]; #if HAVE_LIBSWSCALE - capturePictures = new AVFrame *[v4l2_data.reqbufs.count]; + capturePictures = new AVFrame *[v4l2_data.reqbufs.count]; #endif // HAVE_LIBSWSCALE - for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) - { - struct v4l2_buffer vid_buf; + for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) + { + struct v4l2_buffer vid_buf; - memset( &vid_buf, 0, sizeof(vid_buf) ); + memset( &vid_buf, 0, sizeof(vid_buf) ); - //vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - vid_buf.type = v4l2_data.fmt.type; - //vid_buf.memory = V4L2_MEMORY_MMAP; - vid_buf.memory = v4l2_data.reqbufs.memory; - vid_buf.index = i; + //vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vid_buf.type = v4l2_data.fmt.type; + //vid_buf.memory = V4L2_MEMORY_MMAP; + vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.index = i; - if ( vidioctl( vid_fd, VIDIOC_QUERYBUF, &vid_buf ) < 0 ) - Fatal( "Unable to query video buffer: %s", strerror(errno) ); + if ( vidioctl( vid_fd, VIDIOC_QUERYBUF, &vid_buf ) < 0 ) + Fatal( "Unable to query video buffer: %s", strerror(errno) ); - v4l2_data.buffers[i].length = vid_buf.length; - v4l2_data.buffers[i].start = mmap( NULL, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset ); + v4l2_data.buffers[i].length = vid_buf.length; + v4l2_data.buffers[i].start = mmap( NULL, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset ); - if ( v4l2_data.buffers[i].start == MAP_FAILED ) - Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno ); + if ( v4l2_data.buffers[i].start == MAP_FAILED ) + Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno ); #if HAVE_LIBSWSCALE #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - capturePictures[i] = av_frame_alloc(); + capturePictures[i] = av_frame_alloc(); #else - capturePictures[i] = avcodec_alloc_frame(); + capturePictures[i] = avcodec_alloc_frame(); #endif - if ( !capturePictures[i] ) - Fatal( "Could not allocate picture" ); - avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height ); + if ( !capturePictures[i] ) + Fatal( "Could not allocate picture" ); + avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height ); #endif // HAVE_LIBSWSCALE - } - - Debug( 3, "Configuring video source" ); - - if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) < 0 ) - { - Fatal( "Failed to set camera source %d: %s", channel, strerror(errno) ); - } - - struct v4l2_input input; - v4l2_std_id stdId; - - memset( &input, 0, sizeof(input) ); - - if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) - { - Fatal( "Failed to enumerate input %d: %s", channel, strerror(errno) ); - } - - if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) ) - { - Fatal( "Device does not support video standard %d", standard ); - } - - stdId = standard; - if ( (input.std != V4L2_STD_UNKNOWN) && vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) - { - Fatal( "Failed to set video standard %d: %s", standard, strerror(errno) ); - } - - Contrast(contrast); - Brightness(brightness); - Hue(hue); - Colour(colour); } + + Debug( 3, "Configuring video source" ); + + if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) < 0 ) + { + Fatal( "Failed to set camera source %d: %s", channel, strerror(errno) ); + } + + struct v4l2_input input; + v4l2_std_id stdId; + + memset( &input, 0, sizeof(input) ); + + if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) + { + Fatal( "Failed to enumerate input %d: %s", channel, strerror(errno) ); + } + + if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) ) + { + Fatal( "Device does not support video standard %d", standard ); + } + + stdId = standard; + if ( (input.std != V4L2_STD_UNKNOWN) && vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) + { + Fatal( "Failed to set video standard %d: %s", standard, strerror(errno) ); + } + + Contrast(contrast); + Brightness(brightness); + Hue(hue); + Colour(colour); + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + Debug( 3, "Configuring picture attributes" ); + + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(vid_pic) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + Fatal( "Failed to get picture attributes: %s", strerror(errno) ); + + Debug( 4, "Old P:%d", vid_pic.palette ); + Debug( 4, "Old D:%d", vid_pic.depth ); + Debug( 4, "Old B:%d", vid_pic.brightness ); + Debug( 4, "Old h:%d", vid_pic.hue ); + Debug( 4, "Old Cl:%d", vid_pic.colour ); + Debug( 4, "Old Cn:%d", vid_pic.contrast ); + + switch (vid_pic.palette = palette) { - Debug( 3, "Configuring picture attributes" ); + case VIDEO_PALETTE_RGB32 : + { + vid_pic.depth = 32; + break; + } + case VIDEO_PALETTE_RGB24 : + { + vid_pic.depth = 24; + break; + } + case VIDEO_PALETTE_GREY : + { + vid_pic.depth = 8; + break; + } + case VIDEO_PALETTE_RGB565 : + case VIDEO_PALETTE_YUYV : + case VIDEO_PALETTE_YUV422 : + case VIDEO_PALETTE_YUV420P : + case VIDEO_PALETTE_YUV422P : + default: + { + vid_pic.depth = 16; + break; + } + } - struct video_picture vid_pic; - memset( &vid_pic, 0, sizeof(vid_pic) ); - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) - Fatal( "Failed to get picture attributes: %s", strerror(errno) ); + if ( brightness >= 0 ) vid_pic.brightness = brightness; + if ( hue >= 0 ) vid_pic.hue = hue; + if ( colour >= 0 ) vid_pic.colour = colour; + if ( contrast >= 0 ) vid_pic.contrast = contrast; - Debug( 4, "Old P:%d", vid_pic.palette ); - Debug( 4, "Old D:%d", vid_pic.depth ); - Debug( 4, "Old B:%d", vid_pic.brightness ); - Debug( 4, "Old h:%d", vid_pic.hue ); - Debug( 4, "Old Cl:%d", vid_pic.colour ); - Debug( 4, "Old Cn:%d", vid_pic.contrast ); + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + if ( config.strict_video_config ) + exit(-1); + } - switch (vid_pic.palette = palette) - { - case VIDEO_PALETTE_RGB32 : - { - vid_pic.depth = 32; - break; - } - case VIDEO_PALETTE_RGB24 : - { - vid_pic.depth = 24; - break; - } - case VIDEO_PALETTE_GREY : - { - vid_pic.depth = 8; - break; - } - case VIDEO_PALETTE_RGB565 : - case VIDEO_PALETTE_YUYV : - case VIDEO_PALETTE_YUV422 : - case VIDEO_PALETTE_YUV420P : - case VIDEO_PALETTE_YUV422P : - default: - { - vid_pic.depth = 16; - break; - } - } + Debug( 3, "Configuring window attributes" ); - if ( brightness >= 0 ) vid_pic.brightness = brightness; - if ( hue >= 0 ) vid_pic.hue = hue; - if ( colour >= 0 ) vid_pic.colour = colour; - if ( contrast >= 0 ) vid_pic.contrast = contrast; + struct video_window vid_win; + memset( &vid_win, 0, sizeof(vid_win) ); + if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 ) + { + Error( "Failed to get window attributes: %s", strerror(errno) ); + exit(-1); + } + Debug( 4, "Old X:%d", vid_win.x ); + Debug( 4, "Old Y:%d", vid_win.y ); + Debug( 4, "Old W:%d", vid_win.width ); + Debug( 4, "Old H:%d", vid_win.height ); + + vid_win.x = 0; + vid_win.y = 0; + vid_win.width = width; + vid_win.height = height; + vid_win.flags &= ~VIDEO_WINDOW_INTERLACE; - if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) - { - Error( "Failed to set picture attributes: %s", strerror(errno) ); - if ( config.strict_video_config ) - exit(-1); - } + if ( ioctl( vid_fd, VIDIOCSWIN, &vid_win ) < 0 ) + { + Error( "Failed to set window attributes: %s", strerror(errno) ); + if ( config.strict_video_config ) + exit(-1); + } - Debug( 3, "Configuring window attributes" ); + Info( "vid_win.width = %08x", vid_win.width ); + Info( "vid_win.height = %08x", vid_win.height ); + Info( "vid_win.flags = %08x", vid_win.flags ); - struct video_window vid_win; - memset( &vid_win, 0, sizeof(vid_win) ); - if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 ) - { - Error( "Failed to get window attributes: %s", strerror(errno) ); - exit(-1); - } - Debug( 4, "Old X:%d", vid_win.x ); - Debug( 4, "Old Y:%d", vid_win.y ); - Debug( 4, "Old W:%d", vid_win.width ); - Debug( 4, "Old H:%d", vid_win.height ); - - vid_win.x = 0; - vid_win.y = 0; - vid_win.width = width; - vid_win.height = height; - vid_win.flags &= ~VIDEO_WINDOW_INTERLACE; + Debug( 3, "Setting up request buffers" ); + if ( ioctl( vid_fd, VIDIOCGMBUF, &v4l1_data.frames ) < 0 ) + Fatal( "Failed to setup memory: %s", strerror(errno) ); + if ( channel_count > 1 && !v4l_multi_buffer ) + v4l1_data.frames.frames = 1; + v4l1_data.buffers = new video_mmap[v4l1_data.frames.frames]; + Debug( 4, "vmb.frames = %d", v4l1_data.frames.frames ); + Debug( 4, "vmb.size = %d", v4l1_data.frames.size ); - if ( ioctl( vid_fd, VIDIOCSWIN, &vid_win ) < 0 ) - { - Error( "Failed to set window attributes: %s", strerror(errno) ); - if ( config.strict_video_config ) - exit(-1); - } + Debug( 3, "Setting up %d frame buffers", v4l1_data.frames.frames ); - Info( "vid_win.width = %08x", vid_win.width ); - Info( "vid_win.height = %08x", vid_win.height ); - Info( "vid_win.flags = %08x", vid_win.flags ); - - Debug( 3, "Setting up request buffers" ); - if ( ioctl( vid_fd, VIDIOCGMBUF, &v4l1_data.frames ) < 0 ) - Fatal( "Failed to setup memory: %s", strerror(errno) ); - if ( channel_count > 1 && !v4l_multi_buffer ) - v4l1_data.frames.frames = 1; - v4l1_data.buffers = new video_mmap[v4l1_data.frames.frames]; - Debug( 4, "vmb.frames = %d", v4l1_data.frames.frames ); - Debug( 4, "vmb.size = %d", v4l1_data.frames.size ); - - Debug( 3, "Setting up %d frame buffers", v4l1_data.frames.frames ); - - v4l1_data.bufptr = (unsigned char *)mmap( 0, v4l1_data.frames.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, 0 ); - if ( v4l1_data.bufptr == MAP_FAILED ) - Fatal( "Could not mmap video: %s", strerror(errno) ); + v4l1_data.bufptr = (unsigned char *)mmap( 0, v4l1_data.frames.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, 0 ); + if ( v4l1_data.bufptr == MAP_FAILED ) + Fatal( "Could not mmap video: %s", strerror(errno) ); #if HAVE_LIBSWSCALE - capturePictures = new AVFrame *[v4l1_data.frames.frames]; - for ( int i = 0; i < v4l1_data.frames.frames; i++ ) - { - v4l1_data.buffers[i].frame = i; - v4l1_data.buffers[i].width = width; - v4l1_data.buffers[i].height = height; - v4l1_data.buffers[i].format = palette; + capturePictures = new AVFrame *[v4l1_data.frames.frames]; + for ( int i = 0; i < v4l1_data.frames.frames; i++ ) + { + v4l1_data.buffers[i].frame = i; + v4l1_data.buffers[i].width = width; + v4l1_data.buffers[i].height = height; + v4l1_data.buffers[i].format = palette; #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - capturePictures[i] = av_frame_alloc(); + capturePictures[i] = av_frame_alloc(); #else - capturePictures[i] = avcodec_alloc_frame(); + capturePictures[i] = avcodec_alloc_frame(); #endif - if ( !capturePictures[i] ) - Fatal( "Could not allocate picture" ); - avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height ); - } + if ( !capturePictures[i] ) + Fatal( "Could not allocate picture" ); + avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height ); + } #endif // HAVE_LIBSWSCALE - Debug( 3, "Configuring video source" ); + Debug( 3, "Configuring video source" ); - struct video_channel vid_src; - memset( &vid_src, 0, sizeof(vid_src) ); - vid_src.channel = channel; - if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) - Fatal( "Failed to get camera source: %s", strerror(errno) ); + struct video_channel vid_src; + memset( &vid_src, 0, sizeof(vid_src) ); + vid_src.channel = channel; + if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) + Fatal( "Failed to get camera source: %s", strerror(errno) ); - Debug( 4, "Old C:%d", vid_src.channel ); - Debug( 4, "Old F:%d", vid_src.norm ); - Debug( 4, "Old Fl:%x", vid_src.flags ); - Debug( 4, "Old T:%d", vid_src.type ); + Debug( 4, "Old C:%d", vid_src.channel ); + Debug( 4, "Old F:%d", vid_src.norm ); + Debug( 4, "Old Fl:%x", vid_src.flags ); + Debug( 4, "Old T:%d", vid_src.type ); - vid_src.norm = standard; - vid_src.flags = 0; - vid_src.type = VIDEO_TYPE_CAMERA; - if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 ) - { - Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); - if ( config.strict_video_config ) - exit(-1); - } - - if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 ) - Fatal( "Failed to get window data: %s", strerror(errno) ); - - Info( "vid_win.width = %08x", vid_win.width ); - Info( "vid_win.height = %08x", vid_win.height ); - Info( "vid_win.flags = %08x", vid_win.flags ); - - Debug( 4, "New X:%d", vid_win.x ); - Debug( 4, "New Y:%d", vid_win.y ); - Debug( 4, "New W:%d", vid_win.width ); - Debug( 4, "New H:%d", vid_win.height ); - - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) - Fatal( "Failed to get window data: %s", strerror(errno) ); - - Debug( 4, "New P:%d", vid_pic.palette ); - Debug( 4, "New D:%d", vid_pic.depth ); - Debug( 4, "New B:%d", vid_pic.brightness ); - Debug( 4, "New h:%d", vid_pic.hue ); - Debug( 4, "New Cl:%d", vid_pic.colour ); - Debug( 4, "New Cn:%d", vid_pic.contrast ); + vid_src.norm = standard; + vid_src.flags = 0; + vid_src.type = VIDEO_TYPE_CAMERA; + if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 ) + { + Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); + if ( config.strict_video_config ) + exit(-1); } + + if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 ) + Fatal( "Failed to get window data: %s", strerror(errno) ); + + Info( "vid_win.width = %08x", vid_win.width ); + Info( "vid_win.height = %08x", vid_win.height ); + Info( "vid_win.flags = %08x", vid_win.flags ); + + Debug( 4, "New X:%d", vid_win.x ); + Debug( 4, "New Y:%d", vid_win.y ); + Debug( 4, "New W:%d", vid_win.width ); + Debug( 4, "New H:%d", vid_win.height ); + + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + Fatal( "Failed to get window data: %s", strerror(errno) ); + + Debug( 4, "New P:%d", vid_pic.palette ); + Debug( 4, "New D:%d", vid_pic.depth ); + Debug( 4, "New B:%d", vid_pic.brightness ); + Debug( 4, "New h:%d", vid_pic.hue ); + Debug( 4, "New Cl:%d", vid_pic.colour ); + Debug( 4, "New Cn:%d", vid_pic.contrast ); + } #endif // ZM_HAS_V4L1 } void LocalCamera::Terminate() { #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) - { - Debug( 3, "Terminating video stream" ); - //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - // enum v4l2_buf_type type = v4l2_data.fmt.type; - enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; - if ( vidioctl( vid_fd, VIDIOC_STREAMOFF, &type ) < 0 ) - Error( "Failed to stop capture stream: %s", strerror(errno) ); + if ( v4l_version == 2 ) + { + Debug( 3, "Terminating video stream" ); + //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + // enum v4l2_buf_type type = v4l2_data.fmt.type; + enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; + if ( vidioctl( vid_fd, VIDIOC_STREAMOFF, &type ) < 0 ) + Error( "Failed to stop capture stream: %s", strerror(errno) ); - Debug( 3, "Unmapping video buffers" ); - for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) { + Debug( 3, "Unmapping video buffers" ); + for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) { #if HAVE_LIBSWSCALE - /* Free capture pictures */ + /* Free capture pictures */ #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &capturePictures[i] ); + av_frame_free( &capturePictures[i] ); #else - av_freep( &capturePictures[i] ); + av_freep( &capturePictures[i] ); #endif #endif - if ( munmap( v4l2_data.buffers[i].start, v4l2_data.buffers[i].length ) < 0 ) - Error( "Failed to munmap buffer %d: %s", i, strerror(errno) ); - } - - } - else + if ( munmap( v4l2_data.buffers[i].start, v4l2_data.buffers[i].length ) < 0 ) + Error( "Failed to munmap buffer %d: %s", i, strerror(errno) ); + } + + } + else #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) - { + if ( v4l_version == 1 ) + { #if HAVE_LIBSWSCALE - for(int i=0; i < v4l1_data.frames.frames; i++) { - /* Free capture pictures */ + for(int i=0; i < v4l1_data.frames.frames; i++) { + /* Free capture pictures */ #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &capturePictures[i] ); + av_frame_free( &capturePictures[i] ); #else - av_freep( &capturePictures[i] ); + av_freep( &capturePictures[i] ); #endif - } -#endif - - Debug( 3, "Unmapping video buffers" ); - if ( munmap((char*)v4l1_data.bufptr, v4l1_data.frames.size) < 0 ) - Error( "Failed to munmap buffers: %s", strerror(errno) ); - - delete[] v4l1_data.buffers; } +#endif + + Debug( 3, "Unmapping video buffers" ); + if ( munmap((char*)v4l1_data.bufptr, v4l1_data.frames.size) < 0 ) + Error( "Failed to munmap buffers: %s", strerror(errno) ); + + delete[] v4l1_data.buffers; + } #endif // ZM_HAS_V4L1 - close( vid_fd ); - + close( vid_fd ); + } uint32_t LocalCamera::AutoSelectFormat(int p_colours) { - /* Automatic format selection */ - uint32_t selected_palette = 0; + /* Automatic format selection */ + uint32_t selected_palette = 0; #if ZM_HAS_V4L2 - char fmt_desc[64][32]; - uint32_t fmt_fcc[64]; - v4l2_fmtdesc fmtinfo; - unsigned int nIndex = 0; - //int nRet = 0; // compiler say it isn't used - int enum_fd; - - /* Open the device */ - if ((enum_fd = open( device.c_str(), O_RDWR, 0 )) < 0) { - Error( "Automatic format selection failed to open video device %s: %s", device.c_str(), strerror(errno) ); - return selected_palette; - } - - /* Enumerate available formats */ - memset(&fmtinfo, 0, sizeof(fmtinfo)); - fmtinfo.index = nIndex; - fmtinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - // FIXME This will crash if there are more than 64 formats. - while(vidioctl( enum_fd, VIDIOC_ENUM_FMT, &fmtinfo ) >= 0) { - /* Got a format. Copy it to the array */ - strcpy(fmt_desc[nIndex], (const char*)(fmtinfo.description)); - fmt_fcc[nIndex] = fmtinfo.pixelformat; - - Debug(6, "Got format: %s (%c%c%c%c) at index %d",fmt_desc[nIndex],fmt_fcc[nIndex]&0xff, (fmt_fcc[nIndex]>>8)&0xff, (fmt_fcc[nIndex]>>16)&0xff, (fmt_fcc[nIndex]>>24)&0xff ,nIndex); - - /* Proceed to the next index */ - memset(&fmtinfo, 0, sizeof(fmtinfo)); - fmtinfo.index = ++nIndex; - fmtinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - } - - /* Select format */ - int nIndexUsed = -1; - unsigned int n_preferedformats = 0; - const uint32_t* preferedformats; - if(p_colours == ZM_COLOUR_RGB32) { - /* 32bit */ - preferedformats = prefered_rgb32_formats; - n_preferedformats = sizeof(prefered_rgb32_formats) / sizeof(uint32_t); - } else if(p_colours == ZM_COLOUR_GRAY8) { - /* Grayscale */ - preferedformats = prefered_gray8_formats; - n_preferedformats = sizeof(prefered_gray8_formats) / sizeof(uint32_t); - } else { - /* Assume 24bit */ - preferedformats = prefered_rgb24_formats; - n_preferedformats = sizeof(prefered_rgb24_formats) / sizeof(uint32_t); - } - for( unsigned int i=0; i < n_preferedformats && nIndexUsed < 0; i++ ) { - for( unsigned int j=0; j < nIndex; j++ ) { - if( preferedformats[i] == fmt_fcc[j] ) { - Debug(6, "Choosing format: %s (%c%c%c%c) at index %d",fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j); - /* Found a format! */ - nIndexUsed = j; - break; - } else { - Debug(6, "No match for format: %s (%c%c%c%c) at index %d",fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j); - } - } - } - - /* Have we found a match? */ - if(nIndexUsed >= 0) { - /* Found a match */ - selected_palette = fmt_fcc[nIndexUsed]; - strcpy(palette_desc,fmt_desc[nIndexUsed]); - } - - /* Close the device */ - close(enum_fd); - + char fmt_desc[64][32]; + uint32_t fmt_fcc[64]; + v4l2_fmtdesc fmtinfo; + unsigned int nIndex = 0; + //int nRet = 0; // compiler say it isn't used + int enum_fd; + + /* Open the device */ + if ((enum_fd = open( device.c_str(), O_RDWR, 0 )) < 0) { + Error( "Automatic format selection failed to open video device %s: %s", device.c_str(), strerror(errno) ); + return selected_palette; + } + + /* Enumerate available formats */ + memset(&fmtinfo, 0, sizeof(fmtinfo)); + fmtinfo.index = nIndex; + fmtinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + // FIXME This will crash if there are more than 64 formats. + while(vidioctl( enum_fd, VIDIOC_ENUM_FMT, &fmtinfo ) >= 0) { + /* Got a format. Copy it to the array */ + strcpy(fmt_desc[nIndex], (const char*)(fmtinfo.description)); + fmt_fcc[nIndex] = fmtinfo.pixelformat; + + Debug(6, "Got format: %s (%c%c%c%c) at index %d",fmt_desc[nIndex],fmt_fcc[nIndex]&0xff, (fmt_fcc[nIndex]>>8)&0xff, (fmt_fcc[nIndex]>>16)&0xff, (fmt_fcc[nIndex]>>24)&0xff ,nIndex); + + /* Proceed to the next index */ + memset(&fmtinfo, 0, sizeof(fmtinfo)); + fmtinfo.index = ++nIndex; + fmtinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + + /* Select format */ + int nIndexUsed = -1; + unsigned int n_preferedformats = 0; + const uint32_t* preferedformats; + if(p_colours == ZM_COLOUR_RGB32) { + /* 32bit */ + preferedformats = prefered_rgb32_formats; + n_preferedformats = sizeof(prefered_rgb32_formats) / sizeof(uint32_t); + } else if(p_colours == ZM_COLOUR_GRAY8) { + /* Grayscale */ + preferedformats = prefered_gray8_formats; + n_preferedformats = sizeof(prefered_gray8_formats) / sizeof(uint32_t); + } else { + /* Assume 24bit */ + preferedformats = prefered_rgb24_formats; + n_preferedformats = sizeof(prefered_rgb24_formats) / sizeof(uint32_t); + } + for( unsigned int i=0; i < n_preferedformats && nIndexUsed < 0; i++ ) { + for( unsigned int j=0; j < nIndex; j++ ) { + if( preferedformats[i] == fmt_fcc[j] ) { + Debug(6, "Choosing format: %s (%c%c%c%c) at index %d",fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j); + /* Found a format! */ + nIndexUsed = j; + break; + } else { + Debug(6, "No match for format: %s (%c%c%c%c) at index %d",fmt_desc[j],fmt_fcc[j]&0xff, (fmt_fcc[j]>>8)&0xff, (fmt_fcc[j]>>16)&0xff, (fmt_fcc[j]>>24)&0xff ,j); + } + } + } + + /* Have we found a match? */ + if(nIndexUsed >= 0) { + /* Found a match */ + selected_palette = fmt_fcc[nIndexUsed]; + strcpy(palette_desc,fmt_desc[nIndexUsed]); + } + + /* Close the device */ + close(enum_fd); + #endif /* ZM_HAS_V4L2 */ - return selected_palette; + return selected_palette; } #define capString(test,prefix,yesString,noString,capability) \ - (test) ? (prefix yesString " " capability "\n") : (prefix noString " " capability "\n") + (test) ? (prefix yesString " " capability "\n") : (prefix noString " " capability "\n") bool LocalCamera::GetCurrentSettings( const char *device, char *output, int version, bool verbose ) { - output[0] = 0; + output[0] = 0; - char queryDevice[PATH_MAX] = ""; - int devIndex = 0; - do + char queryDevice[PATH_MAX] = ""; + int devIndex = 0; + do + { + if ( device ) + strcpy( queryDevice, device ); + else + sprintf( queryDevice, "/dev/video%d", devIndex ); + if ( (vid_fd = open(queryDevice, O_RDWR)) <= 0 ) { - if ( device ) - strcpy( queryDevice, device ); - else - sprintf( queryDevice, "/dev/video%d", devIndex ); - if ( (vid_fd = open(queryDevice, O_RDWR)) <= 0 ) - { - if ( device ) - { - Error( "Failed to open video device %s: %s", queryDevice, strerror(errno) ); - if ( verbose ) - sprintf( output+strlen(output), "Error, failed to open video device %s: %s\n", queryDevice, strerror(errno) ); - else - sprintf( output+strlen(output), "error%d\n", errno ); - return( false ); - } - else - { - return( true ); - } - } + if ( device ) + { + Error( "Failed to open video device %s: %s", queryDevice, strerror(errno) ); if ( verbose ) - sprintf( output+strlen(output), "Video Device: %s\n", queryDevice ); + sprintf( output+strlen(output), "Error, failed to open video device %s: %s\n", queryDevice, strerror(errno) ); else - sprintf( output+strlen(output), "d:%s|", queryDevice ); + sprintf( output+strlen(output), "error%d\n", errno ); + return( false ); + } + else + { + return( true ); + } + } + if ( verbose ) + sprintf( output+strlen(output), "Video Device: %s\n", queryDevice ); + else + sprintf( output+strlen(output), "d:%s|", queryDevice ); #if ZM_HAS_V4L2 - if ( version == 2 ) - { - struct v4l2_capability vid_cap; - if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 ) - { - Error( "Failed to query video device: %s", strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to query video capabilities %s: %s\n", queryDevice, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } + if ( version == 2 ) + { + struct v4l2_capability vid_cap; + if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 ) + { + Error( "Failed to query video device: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to query video capabilities %s: %s\n", queryDevice, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } - if ( verbose ) - { - sprintf( output+strlen(output), "General Capabilities\n" ); - sprintf( output+strlen(output), " Driver: %s\n", vid_cap.driver ); - sprintf( output+strlen(output), " Card: %s\n", vid_cap.card ); - sprintf( output+strlen(output), " Bus: %s\n", vid_cap.bus_info ); - sprintf( output+strlen(output), " Version: %u.%u.%u\n", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff ); - sprintf( output+strlen(output), " Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.capabilities, - capString( vid_cap.capabilities&V4L2_CAP_VIDEO_CAPTURE, " ", "Supports", "Does not support", "video capture (X)" ), - capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT, " ", "Supports", "Does not support", "video output" ), - capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OVERLAY, " ", "Supports", "Does not support", "frame buffer overlay" ), - capString( vid_cap.capabilities&V4L2_CAP_VBI_CAPTURE, " ", "Supports", "Does not support", "VBI capture" ), - capString( vid_cap.capabilities&V4L2_CAP_VBI_OUTPUT, " ", "Supports", "Does not support", "VBI output" ), - capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_CAPTURE, " ", "Supports", "Does not support", "sliced VBI capture" ), - capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_OUTPUT, " ", "Supports", "Does not support", "sliced VBI output" ), + if ( verbose ) + { + sprintf( output+strlen(output), "General Capabilities\n" ); + sprintf( output+strlen(output), " Driver: %s\n", vid_cap.driver ); + sprintf( output+strlen(output), " Card: %s\n", vid_cap.card ); + sprintf( output+strlen(output), " Bus: %s\n", vid_cap.bus_info ); + sprintf( output+strlen(output), " Version: %u.%u.%u\n", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff ); + sprintf( output+strlen(output), " Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.capabilities, + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_CAPTURE, " ", "Supports", "Does not support", "video capture (X)" ), + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT, " ", "Supports", "Does not support", "video output" ), + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OVERLAY, " ", "Supports", "Does not support", "frame buffer overlay" ), + capString( vid_cap.capabilities&V4L2_CAP_VBI_CAPTURE, " ", "Supports", "Does not support", "VBI capture" ), + capString( vid_cap.capabilities&V4L2_CAP_VBI_OUTPUT, " ", "Supports", "Does not support", "VBI output" ), + capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_CAPTURE, " ", "Supports", "Does not support", "sliced VBI capture" ), + capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_OUTPUT, " ", "Supports", "Does not support", "sliced VBI output" ), #ifdef V4L2_CAP_VIDEO_OUTPUT_OVERLAY - capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT_OVERLAY, " ", "Supports", "Does not support", "video output overlay" ), + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT_OVERLAY, " ", "Supports", "Does not support", "video output overlay" ), #else // V4L2_CAP_VIDEO_OUTPUT_OVERLAY - "", + "", #endif // V4L2_CAP_VIDEO_OUTPUT_OVERLAY - capString( vid_cap.capabilities&V4L2_CAP_TUNER, " ", "Has", "Does not have", "tuner" ), - capString( vid_cap.capabilities&V4L2_CAP_AUDIO, " ", "Has", "Does not have", "audio in and/or out" ), - capString( vid_cap.capabilities&V4L2_CAP_RADIO, " ", "Has", "Does not have", "radio" ), - capString( vid_cap.capabilities&V4L2_CAP_READWRITE, " ", "Supports", "Does not support", "read/write i/o (X)" ), - capString( vid_cap.capabilities&V4L2_CAP_ASYNCIO, " ", "Supports", "Does not support", "async i/o" ), - capString( vid_cap.capabilities&V4L2_CAP_STREAMING, " ", "Supports", "Does not support", "streaming i/o (X)" ) - ); - } - else - { - sprintf( output+strlen(output), "D:%s|", vid_cap.driver ); - sprintf( output+strlen(output), "C:%s|", vid_cap.card ); - sprintf( output+strlen(output), "B:%s|", vid_cap.bus_info ); - sprintf( output+strlen(output), "V:%u.%u.%u|", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff ); - sprintf( output+strlen(output), "T:0x%x|", vid_cap.capabilities ); - } + capString( vid_cap.capabilities&V4L2_CAP_TUNER, " ", "Has", "Does not have", "tuner" ), + capString( vid_cap.capabilities&V4L2_CAP_AUDIO, " ", "Has", "Does not have", "audio in and/or out" ), + capString( vid_cap.capabilities&V4L2_CAP_RADIO, " ", "Has", "Does not have", "radio" ), + capString( vid_cap.capabilities&V4L2_CAP_READWRITE, " ", "Supports", "Does not support", "read/write i/o (X)" ), + capString( vid_cap.capabilities&V4L2_CAP_ASYNCIO, " ", "Supports", "Does not support", "async i/o" ), + capString( vid_cap.capabilities&V4L2_CAP_STREAMING, " ", "Supports", "Does not support", "streaming i/o (X)" ) + ); + } + else + { + sprintf( output+strlen(output), "D:%s|", vid_cap.driver ); + sprintf( output+strlen(output), "C:%s|", vid_cap.card ); + sprintf( output+strlen(output), "B:%s|", vid_cap.bus_info ); + sprintf( output+strlen(output), "V:%u.%u.%u|", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff ); + sprintf( output+strlen(output), "T:0x%x|", vid_cap.capabilities ); + } + if ( verbose ) + sprintf( output+strlen(output), " Standards:\n" ); + else + sprintf( output+strlen(output), "S:" ); + struct v4l2_standard standard; + int standardIndex = 0; + do + { + memset( &standard, 0, sizeof(standard) ); + standard.index = standardIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUMSTD, &standard ) < 0 ) + { + if ( errno == EINVAL || errno == ENODATA || errno == ENOTTY ) + { + Debug( 6, "Done enumerating standard %d: %d %s", standard.index, errno, strerror(errno) ); + standardIndex = -1; + break; + } + else + { + Error( "Failed to enumerate standard %d: %d %s", standard.index, errno, strerror(errno) ); if ( verbose ) - sprintf( output+strlen(output), " Standards:\n" ); + sprintf( output, "Error, failed to enumerate standard %d: %d %s\n", standard.index, errno, strerror(errno) ); else - sprintf( output+strlen(output), "S:" ); - struct v4l2_standard standard; - int standardIndex = 0; - do - { - memset( &standard, 0, sizeof(standard) ); - standard.index = standardIndex; - - if ( vidioctl( vid_fd, VIDIOC_ENUMSTD, &standard ) < 0 ) - { - if ( errno == EINVAL || errno == ENODATA || errno == ENOTTY ) - { - Debug( 6, "Done enumerating standard %d: %d %s", standard.index, errno, strerror(errno) ); - standardIndex = -1; - break; - } - else - { - Error( "Failed to enumerate standard %d: %d %s", standard.index, errno, strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to enumerate standard %d: %d %s\n", standard.index, errno, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - } - if ( verbose ) - sprintf( output+strlen(output), " %s\n", standard.name ); - else - sprintf( output+strlen(output), "%s/", standard.name ); - } - while ( standardIndex++ >= 0 ); - if ( !verbose && output[strlen(output)-1] == '/') - output[strlen(output)-1] = '|'; - - if ( verbose ) - sprintf( output+strlen(output), " Formats:\n" ); - else - sprintf( output+strlen(output), "F:" ); - struct v4l2_fmtdesc format; - int formatIndex = 0; - do - { - memset( &format, 0, sizeof(format) ); - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - format.index = formatIndex; - - if ( vidioctl( vid_fd, VIDIOC_ENUM_FMT, &format ) < 0 ) - { - if ( errno == EINVAL ) - { - formatIndex = -1; - break; - } - else - { - Error( "Failed to enumerate format %d: %s", format.index, strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - } - if ( verbose ) - sprintf( output+strlen(output), " %s (%c%c%c%c)\n", format.description, format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff ); - else - sprintf( output+strlen(output), "%c%c%c%c/", format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff ); - } - while ( formatIndex++ >= 0 ); - if ( !verbose ) - output[strlen(output)-1] = '|'; - - if(verbose) - sprintf( output+strlen(output), "Crop Capabilities\n" ); - - struct v4l2_cropcap cropcap; - memset( &cropcap, 0, sizeof(cropcap) ); - cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if ( vidioctl( vid_fd, VIDIOC_CROPCAP, &cropcap ) < 0 ) - { - if(errno != EINVAL) { - /* Failed querying crop capability, write error to the log and continue as if crop is not supported */ - Error( "Failed to query crop capabilities: %s", strerror(errno) ); - } - - if(verbose) { - sprintf( output+strlen(output), " Cropping is not supported\n"); - } else { - /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */ - sprintf( output+strlen(output), "B:%dx%d|",0,0); - } - } else { - struct v4l2_crop crop; - memset( &crop, 0, sizeof(crop) ); - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if ( vidioctl( vid_fd, VIDIOC_G_CROP, &crop ) < 0 ) - { - if ( errno != EINVAL ) - { - /* Failed querying crop sizes, write error to the log and continue as if crop is not supported */ - Error( "Failed to query crop: %s", strerror(errno) ); - } - - if ( verbose ) { - sprintf( output+strlen(output), " Cropping is not supported\n"); - } else { - /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */ - sprintf( output+strlen(output), "B:%dx%d|",0,0); - } - } else { - /* Cropping supported */ - if ( verbose ) { - sprintf( output+strlen(output), " Bounds: %d x %d\n", cropcap.bounds.width, cropcap.bounds.height ); - sprintf( output+strlen(output), " Default: %d x %d\n", cropcap.defrect.width, cropcap.defrect.height ); - sprintf( output+strlen(output), " Current: %d x %d\n", crop.c.width, crop.c.height ); - } else { - sprintf( output+strlen(output), "B:%dx%d|", cropcap.bounds.width, cropcap.bounds.height ); - } - } - } /* Crop code */ - - struct v4l2_input input; - int inputIndex = 0; - do - { - memset( &input, 0, sizeof(input) ); - input.index = inputIndex; - - if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) - { - if ( errno == EINVAL ) - { - break; - } - else - { - Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - } - } - while ( inputIndex++ >= 0 ); - - if ( verbose ) - sprintf( output+strlen(output), "Inputs: %d\n", inputIndex ); - else - sprintf( output+strlen(output), "I:%d|", inputIndex ); - - inputIndex = 0; - do - { - memset( &input, 0, sizeof(input) ); - input.index = inputIndex; - - if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) - { - if ( errno == EINVAL ) - { - inputIndex = -1; - break; - } - else - { - Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - } - - if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &input.index ) < 0 ) - { - Error( "Failed to set video input %d: %s", input.index, strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - - if ( verbose ) - { - sprintf( output+strlen(output), " Input %d\n", input.index ); - sprintf( output+strlen(output), " Name: %s\n", input.name ); - sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") ); - sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset ); - sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std ); - } - else - { - sprintf( output+strlen(output), "i%d:%s|", input.index, input.name ); - sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") ); - sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std ); - } - - if ( verbose ) - { - sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) ); - sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) ); - sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) ); - sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) ); - } - else - { - sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 ); - sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 ); - sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 ); - sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 ); - } - } - while ( inputIndex++ >= 0 ); - if ( !verbose ) - output[strlen(output)-1] = '\n'; + sprintf( output, "error%d\n", errno ); + return( false ); + } } + if ( verbose ) + sprintf( output+strlen(output), " %s\n", standard.name ); + else + sprintf( output+strlen(output), "%s/", standard.name ); + } + while ( standardIndex++ >= 0 ); + if ( !verbose && output[strlen(output)-1] == '/') + output[strlen(output)-1] = '|'; + + if ( verbose ) + sprintf( output+strlen(output), " Formats:\n" ); + else + sprintf( output+strlen(output), "F:" ); + struct v4l2_fmtdesc format; + int formatIndex = 0; + do + { + memset( &format, 0, sizeof(format) ); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.index = formatIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUM_FMT, &format ) < 0 ) + { + if ( errno == EINVAL ) + { + formatIndex = -1; + break; + } + else + { + Error( "Failed to enumerate format %d: %s", format.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + if ( verbose ) + sprintf( output+strlen(output), " %s (%c%c%c%c)\n", format.description, format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff ); + else + sprintf( output+strlen(output), "%c%c%c%c/", format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff ); + } + while ( formatIndex++ >= 0 ); + if ( !verbose ) + output[strlen(output)-1] = '|'; + + if(verbose) + sprintf( output+strlen(output), "Crop Capabilities\n" ); + + struct v4l2_cropcap cropcap; + memset( &cropcap, 0, sizeof(cropcap) ); + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if ( vidioctl( vid_fd, VIDIOC_CROPCAP, &cropcap ) < 0 ) + { + if(errno != EINVAL) { + /* Failed querying crop capability, write error to the log and continue as if crop is not supported */ + Error( "Failed to query crop capabilities: %s", strerror(errno) ); + } + + if(verbose) { + sprintf( output+strlen(output), " Cropping is not supported\n"); + } else { + /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */ + sprintf( output+strlen(output), "B:%dx%d|",0,0); + } + } else { + struct v4l2_crop crop; + memset( &crop, 0, sizeof(crop) ); + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if ( vidioctl( vid_fd, VIDIOC_G_CROP, &crop ) < 0 ) + { + if ( errno != EINVAL ) + { + /* Failed querying crop sizes, write error to the log and continue as if crop is not supported */ + Error( "Failed to query crop: %s", strerror(errno) ); + } + + if ( verbose ) { + sprintf( output+strlen(output), " Cropping is not supported\n"); + } else { + /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */ + sprintf( output+strlen(output), "B:%dx%d|",0,0); + } + } else { + /* Cropping supported */ + if ( verbose ) { + sprintf( output+strlen(output), " Bounds: %d x %d\n", cropcap.bounds.width, cropcap.bounds.height ); + sprintf( output+strlen(output), " Default: %d x %d\n", cropcap.defrect.width, cropcap.defrect.height ); + sprintf( output+strlen(output), " Current: %d x %d\n", crop.c.width, crop.c.height ); + } else { + sprintf( output+strlen(output), "B:%dx%d|", cropcap.bounds.width, cropcap.bounds.height ); + } + } + } /* Crop code */ + + struct v4l2_input input; + int inputIndex = 0; + do + { + memset( &input, 0, sizeof(input) ); + input.index = inputIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) + { + if ( errno == EINVAL ) + { + break; + } + else + { + Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + } + while ( inputIndex++ >= 0 ); + + if ( verbose ) + sprintf( output+strlen(output), "Inputs: %d\n", inputIndex ); + else + sprintf( output+strlen(output), "I:%d|", inputIndex ); + + inputIndex = 0; + do + { + memset( &input, 0, sizeof(input) ); + input.index = inputIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) + { + if ( errno == EINVAL ) + { + inputIndex = -1; + break; + } + else + { + Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + + if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &input.index ) < 0 ) + { + Error( "Failed to set video input %d: %s", input.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + + if ( verbose ) + { + sprintf( output+strlen(output), " Input %d\n", input.index ); + sprintf( output+strlen(output), " Name: %s\n", input.name ); + sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") ); + sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset ); + sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std ); + } + else + { + sprintf( output+strlen(output), "i%d:%s|", input.index, input.name ); + sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") ); + sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std ); + } + + if ( verbose ) + { + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) ); + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) ); + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) ); + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) ); + } + else + { + sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 ); + sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 ); + sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 ); + sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 ); + } + } + while ( inputIndex++ >= 0 ); + if ( !verbose ) + output[strlen(output)-1] = '\n'; + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( version == 1 ) + if ( version == 1 ) + { + struct video_capability vid_cap; + memset( &vid_cap, 0, sizeof(video_capability) ); + if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) + { + Error( "Failed to get video capabilities: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Video Capabilities\n" ); + sprintf( output+strlen(output), " Name: %s\n", vid_cap.name ); + sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type, + vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"", + vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"", + vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"", + vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"", + vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"", + vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"", + vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"", + vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"", + vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"", + vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"", + vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"", + vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"", + vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"", + vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":"" + ); + sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels ); + sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios ); + sprintf( output+strlen(output), " Maximum Width: %d\n", vid_cap.maxwidth ); + sprintf( output+strlen(output), " Maximum Height: %d\n", vid_cap.maxheight ); + sprintf( output+strlen(output), " Minimum Width: %d\n", vid_cap.minwidth ); + sprintf( output+strlen(output), " Minimum Height: %d\n", vid_cap.minheight ); + } + else + { + sprintf( output+strlen(output), "N:%s|", vid_cap.name ); + sprintf( output+strlen(output), "T:%d|", vid_cap.type ); + sprintf( output+strlen(output), "nC:%d|", vid_cap.channels ); + sprintf( output+strlen(output), "nA:%d|", vid_cap.audios ); + sprintf( output+strlen(output), "mxW:%d|", vid_cap.maxwidth ); + sprintf( output+strlen(output), "mxH:%d|", vid_cap.maxheight ); + sprintf( output+strlen(output), "mnW:%d|", vid_cap.minwidth ); + sprintf( output+strlen(output), "mnH:%d|", vid_cap.minheight ); + } + + struct video_window vid_win; + memset( &vid_win, 0, sizeof(video_window) ); + if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win ) < 0 ) + { + Error( "Failed to get window attributes: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get window attributes: %s\n", strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Window Attributes\n" ); + sprintf( output+strlen(output), " X Offset: %d\n", vid_win.x ); + sprintf( output+strlen(output), " Y Offset: %d\n", vid_win.y ); + sprintf( output+strlen(output), " Width: %d\n", vid_win.width ); + sprintf( output+strlen(output), " Height: %d\n", vid_win.height ); + } + else + { + sprintf( output+strlen(output), "X:%d|", vid_win.x ); + sprintf( output+strlen(output), "Y:%d|", vid_win.y ); + sprintf( output+strlen(output), "W:%d|", vid_win.width ); + sprintf( output+strlen(output), "H:%d|", vid_win.height ); + } + + struct video_picture vid_pic; + memset( &vid_cap, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic ) < 0 ) + { + Error( "Failed to get picture attributes: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get picture attributes: %s\n", strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Picture Attributes\n" ); + sprintf( output+strlen(output), " Palette: %d - %s\n", vid_pic.palette, + vid_pic.palette==VIDEO_PALETTE_GREY?"Linear greyscale":( + vid_pic.palette==VIDEO_PALETTE_HI240?"High 240 cube (BT848)":( + vid_pic.palette==VIDEO_PALETTE_RGB565?"565 16 bit RGB":( + vid_pic.palette==VIDEO_PALETTE_RGB24?"24bit RGB":( + vid_pic.palette==VIDEO_PALETTE_RGB32?"32bit RGB":( + vid_pic.palette==VIDEO_PALETTE_RGB555?"555 15bit RGB":( + vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422 capture":( + vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":( + vid_pic.palette==VIDEO_PALETTE_UYVY?"UVYV":( + vid_pic.palette==VIDEO_PALETTE_YUV420?"YUV420":( + vid_pic.palette==VIDEO_PALETTE_YUV411?"YUV411 capture":( + vid_pic.palette==VIDEO_PALETTE_RAW?"RAW capture (BT848)":( + vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":( + vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422":( + vid_pic.palette==VIDEO_PALETTE_YUV422P?"YUV 4:2:2 Planar":( + vid_pic.palette==VIDEO_PALETTE_YUV411P?"YUV 4:1:1 Planar":( + vid_pic.palette==VIDEO_PALETTE_YUV420P?"YUV 4:2:0 Planar":( + vid_pic.palette==VIDEO_PALETTE_YUV410P?"YUV 4:1:0 Planar":"Unknown" + )))))))))))))))))); + sprintf( output+strlen(output), " Colour Depth: %d\n", vid_pic.depth ); + sprintf( output+strlen(output), " Brightness: %d\n", vid_pic.brightness ); + sprintf( output+strlen(output), " Hue: %d\n", vid_pic.hue ); + sprintf( output+strlen(output), " Colour :%d\n", vid_pic.colour ); + sprintf( output+strlen(output), " Contrast: %d\n", vid_pic.contrast ); + sprintf( output+strlen(output), " Whiteness: %d\n", vid_pic.whiteness ); + } + else + { + sprintf( output+strlen(output), "P:%d|", vid_pic.palette ); + sprintf( output+strlen(output), "D:%d|", vid_pic.depth ); + sprintf( output+strlen(output), "B:%d|", vid_pic.brightness ); + sprintf( output+strlen(output), "h:%d|", vid_pic.hue ); + sprintf( output+strlen(output), "Cl:%d|", vid_pic.colour ); + sprintf( output+strlen(output), "Cn:%d|", vid_pic.contrast ); + sprintf( output+strlen(output), "w:%d|", vid_pic.whiteness ); + } + + for ( int chan = 0; chan < vid_cap.channels; chan++ ) + { + struct video_channel vid_src; + memset( &vid_src, 0, sizeof(video_channel) ); + vid_src.channel = chan; + if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src ) < 0 ) { - struct video_capability vid_cap; - memset( &vid_cap, 0, sizeof(video_capability) ); - if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) - { - Error( "Failed to get video capabilities: %s", strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - if ( verbose ) - { - sprintf( output+strlen(output), "Video Capabilities\n" ); - sprintf( output+strlen(output), " Name: %s\n", vid_cap.name ); - sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type, - vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"", - vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"", - vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"", - vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"", - vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"", - vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"", - vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"", - vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"", - vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"", - vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"", - vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"", - vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"", - vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"", - vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":"" - ); - sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels ); - sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios ); - sprintf( output+strlen(output), " Maximum Width: %d\n", vid_cap.maxwidth ); - sprintf( output+strlen(output), " Maximum Height: %d\n", vid_cap.maxheight ); - sprintf( output+strlen(output), " Minimum Width: %d\n", vid_cap.minwidth ); - sprintf( output+strlen(output), " Minimum Height: %d\n", vid_cap.minheight ); - } - else - { - sprintf( output+strlen(output), "N:%s|", vid_cap.name ); - sprintf( output+strlen(output), "T:%d|", vid_cap.type ); - sprintf( output+strlen(output), "nC:%d|", vid_cap.channels ); - sprintf( output+strlen(output), "nA:%d|", vid_cap.audios ); - sprintf( output+strlen(output), "mxW:%d|", vid_cap.maxwidth ); - sprintf( output+strlen(output), "mxH:%d|", vid_cap.maxheight ); - sprintf( output+strlen(output), "mnW:%d|", vid_cap.minwidth ); - sprintf( output+strlen(output), "mnH:%d|", vid_cap.minheight ); - } - - struct video_window vid_win; - memset( &vid_win, 0, sizeof(video_window) ); - if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win ) < 0 ) - { - Error( "Failed to get window attributes: %s", strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to get window attributes: %s\n", strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - if ( verbose ) - { - sprintf( output+strlen(output), "Window Attributes\n" ); - sprintf( output+strlen(output), " X Offset: %d\n", vid_win.x ); - sprintf( output+strlen(output), " Y Offset: %d\n", vid_win.y ); - sprintf( output+strlen(output), " Width: %d\n", vid_win.width ); - sprintf( output+strlen(output), " Height: %d\n", vid_win.height ); - } - else - { - sprintf( output+strlen(output), "X:%d|", vid_win.x ); - sprintf( output+strlen(output), "Y:%d|", vid_win.y ); - sprintf( output+strlen(output), "W:%d|", vid_win.width ); - sprintf( output+strlen(output), "H:%d|", vid_win.height ); - } - - struct video_picture vid_pic; - memset( &vid_cap, 0, sizeof(video_picture) ); - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic ) < 0 ) - { - Error( "Failed to get picture attributes: %s", strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to get picture attributes: %s\n", strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - if ( verbose ) - { - sprintf( output+strlen(output), "Picture Attributes\n" ); - sprintf( output+strlen(output), " Palette: %d - %s\n", vid_pic.palette, - vid_pic.palette==VIDEO_PALETTE_GREY?"Linear greyscale":( - vid_pic.palette==VIDEO_PALETTE_HI240?"High 240 cube (BT848)":( - vid_pic.palette==VIDEO_PALETTE_RGB565?"565 16 bit RGB":( - vid_pic.palette==VIDEO_PALETTE_RGB24?"24bit RGB":( - vid_pic.palette==VIDEO_PALETTE_RGB32?"32bit RGB":( - vid_pic.palette==VIDEO_PALETTE_RGB555?"555 15bit RGB":( - vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422 capture":( - vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":( - vid_pic.palette==VIDEO_PALETTE_UYVY?"UVYV":( - vid_pic.palette==VIDEO_PALETTE_YUV420?"YUV420":( - vid_pic.palette==VIDEO_PALETTE_YUV411?"YUV411 capture":( - vid_pic.palette==VIDEO_PALETTE_RAW?"RAW capture (BT848)":( - vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":( - vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422":( - vid_pic.palette==VIDEO_PALETTE_YUV422P?"YUV 4:2:2 Planar":( - vid_pic.palette==VIDEO_PALETTE_YUV411P?"YUV 4:1:1 Planar":( - vid_pic.palette==VIDEO_PALETTE_YUV420P?"YUV 4:2:0 Planar":( - vid_pic.palette==VIDEO_PALETTE_YUV410P?"YUV 4:1:0 Planar":"Unknown" - )))))))))))))))))); - sprintf( output+strlen(output), " Colour Depth: %d\n", vid_pic.depth ); - sprintf( output+strlen(output), " Brightness: %d\n", vid_pic.brightness ); - sprintf( output+strlen(output), " Hue: %d\n", vid_pic.hue ); - sprintf( output+strlen(output), " Colour :%d\n", vid_pic.colour ); - sprintf( output+strlen(output), " Contrast: %d\n", vid_pic.contrast ); - sprintf( output+strlen(output), " Whiteness: %d\n", vid_pic.whiteness ); - } - else - { - sprintf( output+strlen(output), "P:%d|", vid_pic.palette ); - sprintf( output+strlen(output), "D:%d|", vid_pic.depth ); - sprintf( output+strlen(output), "B:%d|", vid_pic.brightness ); - sprintf( output+strlen(output), "h:%d|", vid_pic.hue ); - sprintf( output+strlen(output), "Cl:%d|", vid_pic.colour ); - sprintf( output+strlen(output), "Cn:%d|", vid_pic.contrast ); - sprintf( output+strlen(output), "w:%d|", vid_pic.whiteness ); - } - - for ( int chan = 0; chan < vid_cap.channels; chan++ ) - { - struct video_channel vid_src; - memset( &vid_src, 0, sizeof(video_channel) ); - vid_src.channel = chan; - if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src ) < 0 ) - { - Error( "Failed to get channel %d attributes: %s", chan, strerror(errno) ); - if ( verbose ) - sprintf( output, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno) ); - else - sprintf( output, "error%d\n", errno ); - return( false ); - } - if ( verbose ) - { - sprintf( output+strlen(output), "Channel %d Attributes\n", chan ); - sprintf( output+strlen(output), " Name: %s\n", vid_src.name ); - sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel ); - sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags, - vid_src.flags&VIDEO_VC_TUNER?" Channel has a tuner\n":"", - vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":"" - ); - sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type, - vid_src.type==VIDEO_TYPE_TV?"TV":( - vid_src.type==VIDEO_TYPE_CAMERA?"Camera":"Unknown" - )); - sprintf( output+strlen(output), " Format: %d - %s\n", vid_src.norm, - vid_src.norm==VIDEO_MODE_PAL?"PAL":( - vid_src.norm==VIDEO_MODE_NTSC?"NTSC":( - vid_src.norm==VIDEO_MODE_SECAM?"SECAM":( - vid_src.norm==VIDEO_MODE_AUTO?"AUTO":"Unknown" - )))); - } - else - { - sprintf( output+strlen(output), "n%d:%s|", chan, vid_src.name ); - sprintf( output+strlen(output), "C%d:%d|", chan, vid_src.channel ); - sprintf( output+strlen(output), "Fl%d:%x|", chan, vid_src.flags ); - sprintf( output+strlen(output), "T%d:%d|", chan, vid_src.type ); - sprintf( output+strlen(output), "F%d:%d%s|", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," ); - } - } - if ( !verbose ) - output[strlen(output)-1] = '\n'; + Error( "Failed to get channel %d attributes: %s", chan, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); } -#endif // ZM_HAS_V4L1 - close( vid_fd ); - if ( device ) - break; + if ( verbose ) + { + sprintf( output+strlen(output), "Channel %d Attributes\n", chan ); + sprintf( output+strlen(output), " Name: %s\n", vid_src.name ); + sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel ); + sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags, + vid_src.flags&VIDEO_VC_TUNER?" Channel has a tuner\n":"", + vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":"" + ); + sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type, + vid_src.type==VIDEO_TYPE_TV?"TV":( + vid_src.type==VIDEO_TYPE_CAMERA?"Camera":"Unknown" + )); + sprintf( output+strlen(output), " Format: %d - %s\n", vid_src.norm, + vid_src.norm==VIDEO_MODE_PAL?"PAL":( + vid_src.norm==VIDEO_MODE_NTSC?"NTSC":( + vid_src.norm==VIDEO_MODE_SECAM?"SECAM":( + vid_src.norm==VIDEO_MODE_AUTO?"AUTO":"Unknown" + )))); + } + else + { + sprintf( output+strlen(output), "n%d:%s|", chan, vid_src.name ); + sprintf( output+strlen(output), "C%d:%d|", chan, vid_src.channel ); + sprintf( output+strlen(output), "Fl%d:%x|", chan, vid_src.flags ); + sprintf( output+strlen(output), "T%d:%d|", chan, vid_src.type ); + sprintf( output+strlen(output), "F%d:%d%s|", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," ); + } + } + if ( !verbose ) + output[strlen(output)-1] = '\n'; } - while ( ++devIndex < 32 ); - return( true ); +#endif // ZM_HAS_V4L1 + close( vid_fd ); + if ( device ) + break; + } + while ( ++devIndex < 32 ); + return( true ); } int LocalCamera::Brightness( int p_brightness ) { #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_BRIGHTNESS; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) { - struct v4l2_control vid_control; - - memset( &vid_control, 0, sizeof(vid_control) ); - vid_control.id = V4L2_CID_BRIGHTNESS; - - if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) - { - if ( errno != EINVAL ) - Error( "Unable to query brightness: %s", strerror(errno) ) - else - Warning( "Brightness control is not supported" ) - //Info( "Brightness 1 %d", vid_control.value ); - } - else if ( p_brightness >= 0 ) - { - vid_control.value = p_brightness; - - //Info( "Brightness 2 %d", vid_control.value ); - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) ) - { - if ( errno != ERANGE ) - Error( "Unable to set brightness: %s", strerror(errno) ) - else - Warning( "Given brightness value (%d) may be out-of-range", p_brightness ) - } - //Info( "Brightness 3 %d", vid_control.value ); - } - return( vid_control.value ); + if ( errno != EINVAL ) + Error( "Unable to query brightness: %s", strerror(errno) ) + else + Warning( "Brightness control is not supported" ) + //Info( "Brightness 1 %d", vid_control.value ); } + else if ( p_brightness >= 0 ) + { + vid_control.value = p_brightness; + + //Info( "Brightness 2 %d", vid_control.value ); + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) ) + { + if ( errno != ERANGE ) + Error( "Unable to set brightness: %s", strerror(errno) ) + else + Warning( "Given brightness value (%d) may be out-of-range", p_brightness ) + } + //Info( "Brightness 3 %d", vid_control.value ); + } + return( vid_control.value ); + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) { - struct video_picture vid_pic; - memset( &vid_pic, 0, sizeof(video_picture) ); - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) - { - Error( "Failed to get picture attributes: %s", strerror(errno) ); - return( -1 ); - } - - if ( p_brightness >= 0 ) - { - vid_pic.brightness = p_brightness; - if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) - { - Error( "Failed to set picture attributes: %s", strerror(errno) ); - return( -1 ); - } - } - return( vid_pic.brightness ); + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); } + + if ( p_brightness >= 0 ) + { + vid_pic.brightness = p_brightness; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.brightness ); + } #endif // ZM_HAS_V4L1 - return( -1 ); + return( -1 ); } int LocalCamera::Hue( int p_hue ) { #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_HUE; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) { - struct v4l2_control vid_control; - - memset( &vid_control, 0, sizeof(vid_control) ); - vid_control.id = V4L2_CID_HUE; - - if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) - { - if ( errno != EINVAL ) - Error( "Unable to query hue: %s", strerror(errno) ) - else - Warning( "Hue control is not supported" ) - } - else if ( p_hue >= 0 ) - { - vid_control.value = p_hue; - - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) - { - if ( errno != ERANGE ) - Error( "Unable to set hue: %s", strerror(errno) ) - else - Warning( "Given hue value (%d) may be out-of-range", p_hue ) - } - } - return( vid_control.value ); + if ( errno != EINVAL ) + Error( "Unable to query hue: %s", strerror(errno) ) + else + Warning( "Hue control is not supported" ) } + else if ( p_hue >= 0 ) + { + vid_control.value = p_hue; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) + { + if ( errno != ERANGE ) + Error( "Unable to set hue: %s", strerror(errno) ) + else + Warning( "Given hue value (%d) may be out-of-range", p_hue ) + } + } + return( vid_control.value ); + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) { - struct video_picture vid_pic; - memset( &vid_pic, 0, sizeof(video_picture) ); - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) - { - Error( "Failed to get picture attributes: %s", strerror(errno) ); - return( -1 ); - } - - if ( p_hue >= 0 ) - { - vid_pic.hue = p_hue; - if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) - { - Error( "Failed to set picture attributes: %s", strerror(errno) ); - return( -1 ); - } - } - return( vid_pic.hue ); + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); } + + if ( p_hue >= 0 ) + { + vid_pic.hue = p_hue; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.hue ); + } #endif // ZM_HAS_V4L1 - return( -1 ); + return( -1 ); } int LocalCamera::Colour( int p_colour ) { #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_SATURATION; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) { - struct v4l2_control vid_control; - - memset( &vid_control, 0, sizeof(vid_control) ); - vid_control.id = V4L2_CID_SATURATION; - - if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) - { - if ( errno != EINVAL ) - Error( "Unable to query saturation: %s", strerror(errno) ) - else - Warning( "Saturation control is not supported" ) - } - else if ( p_colour >= 0 ) - { - vid_control.value = p_colour; - - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) - { - if ( errno != ERANGE ) - Error( "Unable to set saturation: %s", strerror(errno) ) - else - Warning( "Given saturation value (%d) may be out-of-range", p_colour ) - } - } - return( vid_control.value ); + if ( errno != EINVAL ) + Error( "Unable to query saturation: %s", strerror(errno) ) + else + Warning( "Saturation control is not supported" ) } + else if ( p_colour >= 0 ) + { + vid_control.value = p_colour; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) + { + if ( errno != ERANGE ) + Error( "Unable to set saturation: %s", strerror(errno) ) + else + Warning( "Given saturation value (%d) may be out-of-range", p_colour ) + } + } + return( vid_control.value ); + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) { - struct video_picture vid_pic; - memset( &vid_pic, 0, sizeof(video_picture) ); - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) - { - Error( "Failed to get picture attributes: %s", strerror(errno) ); - return( -1 ); - } - - if ( p_colour >= 0 ) - { - vid_pic.colour = p_colour; - if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) - { - Error( "Failed to set picture attributes: %s", strerror(errno) ); - return( -1 ); - } - } - return( vid_pic.colour ); + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); } + + if ( p_colour >= 0 ) + { + vid_pic.colour = p_colour; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.colour ); + } #endif // ZM_HAS_V4L1 - return( -1 ); + return( -1 ); } int LocalCamera::Contrast( int p_contrast ) { #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_CONTRAST; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) { - struct v4l2_control vid_control; - - memset( &vid_control, 0, sizeof(vid_control) ); - vid_control.id = V4L2_CID_CONTRAST; - - if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) - { - if ( errno != EINVAL ) - Error( "Unable to query contrast: %s", strerror(errno) ) - else - Warning( "Contrast control is not supported" ) - } - else if ( p_contrast >= 0 ) - { - vid_control.value = p_contrast; - - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) ) - { - if ( errno != ERANGE ) - Error( "Unable to set contrast: %s", strerror(errno) ) - else - Warning( "Given contrast value (%d) may be out-of-range", p_contrast ) - } - } - return( vid_control.value ); + if ( errno != EINVAL ) + Error( "Unable to query contrast: %s", strerror(errno) ) + else + Warning( "Contrast control is not supported" ) } + else if ( p_contrast >= 0 ) + { + vid_control.value = p_contrast; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) ) + { + if ( errno != ERANGE ) + Error( "Unable to set contrast: %s", strerror(errno) ) + else + Warning( "Given contrast value (%d) may be out-of-range", p_contrast ) + } + } + return( vid_control.value ); + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) { - struct video_picture vid_pic; - memset( &vid_pic, 0, sizeof(video_picture) ); - if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) - { - Error( "Failed to get picture attributes: %s", strerror(errno) ); - return( -1 ); - } - - if ( p_contrast >= 0 ) - { - vid_pic.contrast = p_contrast; - if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) - { - Error( "Failed to set picture attributes: %s", strerror(errno) ); - return( -1 ); - } - } - return( vid_pic.contrast ); + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); } + + if ( p_contrast >= 0 ) + { + vid_pic.contrast = p_contrast; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.contrast ); + } #endif // ZM_HAS_V4L1 - return( -1 ); + return( -1 ); } int LocalCamera::PrimeCapture() { - Initialise(); + Initialise(); - Debug( 2, "Priming capture" ); + Debug( 2, "Priming capture" ); +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + Debug( 3, "Queueing buffers" ); + for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) + { + struct v4l2_buffer vid_buf; + + memset( &vid_buf, 0, sizeof(vid_buf) ); + + vid_buf.type = v4l2_data.fmt.type; + vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.index = frame; + + if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) + Fatal( "Failed to queue buffer %d: %s", frame, strerror(errno) ); + } + v4l2_data.bufptr = NULL; + + Debug( 3, "Starting video stream" ); + //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + //enum v4l2_buf_type type = v4l2_data.fmt.type; + enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; + if ( vidioctl( vid_fd, VIDIOC_STREAMON, &type ) < 0 ) + Fatal( "Failed to start capture stream: %s", strerror(errno) ); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) + { + Debug( 3, "Queueing frame %d", frame ); + if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 ) + { + Error( "Capture failure for frame %d: %s", frame, strerror(errno) ); + return( -1 ); + } + } + } +#endif // ZM_HAS_V4L1 + + return( 0 ); +} + +int LocalCamera::PreCapture() +{ + Debug( 2, "Pre-capturing" ); + return( 0 ); +} + +int LocalCamera::Capture( Image &image ) +{ + Debug( 3, "Capturing" ); + static uint8_t* buffer = NULL; + static uint8_t* directbuffer = NULL; + static int capture_frame = -1; + int buffer_bytesused = 0; + + int captures_per_frame = 1; + if ( channel_count > 1 ) + captures_per_frame = v4l_captures_per_frame; + if ( captures_per_frame <= 0 ) { + captures_per_frame = 1; + Warning( "Invalid Captures Per Frame setting: %d", captures_per_frame ); + } + + + // Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer + if ( channel_prime ) + { #if ZM_HAS_V4L2 if ( v4l_version == 2 ) { - Debug( 3, "Queueing buffers" ); - for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) + static struct v4l2_buffer vid_buf; + + memset( &vid_buf, 0, sizeof(vid_buf) ); + + vid_buf.type = v4l2_data.fmt.type; + //vid_buf.memory = V4L2_MEMORY_MMAP; + vid_buf.memory = v4l2_data.reqbufs.memory; + + Debug( 3, "Capturing %d frames", captures_per_frame ); + while ( captures_per_frame ) + { + if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 ) { - struct v4l2_buffer vid_buf; - - memset( &vid_buf, 0, sizeof(vid_buf) ); - - vid_buf.type = v4l2_data.fmt.type; - vid_buf.memory = v4l2_data.reqbufs.memory; - vid_buf.index = frame; - - if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) - Fatal( "Failed to queue buffer %d: %s", frame, strerror(errno) ); + if ( errno == EIO ) + Warning( "Capture failure, possible signal loss?: %s", strerror(errno) ) + else + Error( "Unable to capture frame %d: %s", vid_buf.index, strerror(errno) ) + return( -1 ); } - v4l2_data.bufptr = NULL; - Debug( 3, "Starting video stream" ); - //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - //enum v4l2_buf_type type = v4l2_data.fmt.type; - enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; - if ( vidioctl( vid_fd, VIDIOC_STREAMON, &type ) < 0 ) - Fatal( "Failed to start capture stream: %s", strerror(errno) ); + v4l2_data.bufptr = &vid_buf; + capture_frame = v4l2_data.bufptr->index; + if ( --captures_per_frame ) + { + if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) + { + Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) ); + return( -1 ); + } + } + } + + Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel ); + + buffer = (unsigned char *)v4l2_data.buffers[v4l2_data.bufptr->index].start; + buffer_bytesused = v4l2_data.bufptr->bytesused; + + if((v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) != (width * height)) { + Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height); + } + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 if ( v4l_version == 1 ) { - for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) + Debug( 3, "Capturing %d frames", captures_per_frame ); + while ( captures_per_frame ) + { + Debug( 3, "Syncing frame %d", v4l1_data.active_frame ); + if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 ) { - Debug( 3, "Queueing frame %d", frame ); - if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 ) - { - Error( "Capture failure for frame %d: %s", frame, strerror(errno) ); - return( -1 ); - } + Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) ); + return( -1 ); } + captures_per_frame--; + if ( captures_per_frame ) + { + Debug( 3, "Capturing frame %d", v4l1_data.active_frame ); + if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) + { + Error( "Capture failure for buffer %d (%d): %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) ); + return( -1 ); + } + } + } + capture_frame = v4l1_data.active_frame; + Debug( 3, "Captured %d for channel %d", capture_frame, channel ); + + buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame]; } #endif // ZM_HAS_V4L1 - - return( 0 ); -} - -int LocalCamera::PreCapture() -{ - Debug( 2, "Pre-capturing" ); - return( 0 ); -} - -int LocalCamera::Capture( Image &image ) -{ - Debug( 3, "Capturing" ); - static uint8_t* buffer = NULL; - static uint8_t* directbuffer = NULL; - static int capture_frame = -1; - int buffer_bytesused = 0; - - int captures_per_frame = 1; - if ( channel_count > 1 ) - captures_per_frame = v4l_captures_per_frame; - if ( captures_per_frame <= 0 ) { - captures_per_frame = 1; - Warning( "Invalid Captures Per Frame setting: %d", captures_per_frame ); - } - - - // Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer - if ( channel_prime ) - { -#if ZM_HAS_V4L2 - if ( v4l_version == 2 ) - { - static struct v4l2_buffer vid_buf; - - memset( &vid_buf, 0, sizeof(vid_buf) ); - - vid_buf.type = v4l2_data.fmt.type; - //vid_buf.memory = V4L2_MEMORY_MMAP; - vid_buf.memory = v4l2_data.reqbufs.memory; - - Debug( 3, "Capturing %d frames", captures_per_frame ); - while ( captures_per_frame ) - { - if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 ) - { - if ( errno == EIO ) - Warning( "Capture failure, possible signal loss?: %s", strerror(errno) ) - else - Error( "Unable to capture frame %d: %s", vid_buf.index, strerror(errno) ) - return( -1 ); - } - - v4l2_data.bufptr = &vid_buf; - capture_frame = v4l2_data.bufptr->index; - if ( --captures_per_frame ) - { - if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) - { - Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) ); - return( -1 ); - } - } - } - - Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel ); - - buffer = (unsigned char *)v4l2_data.buffers[v4l2_data.bufptr->index].start; - buffer_bytesused = v4l2_data.bufptr->bytesused; - - if((v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) != (width * height)) { - Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height); - } - - } -#endif // ZM_HAS_V4L2 -#if ZM_HAS_V4L1 - if ( v4l_version == 1 ) - { - Debug( 3, "Capturing %d frames", captures_per_frame ); - while ( captures_per_frame ) - { - Debug( 3, "Syncing frame %d", v4l1_data.active_frame ); - if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 ) - { - Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) ); - return( -1 ); - } - captures_per_frame--; - if ( captures_per_frame ) - { - Debug( 3, "Capturing frame %d", v4l1_data.active_frame ); - if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) - { - Error( "Capture failure for buffer %d (%d): %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) ); - return( -1 ); - } - } - } - capture_frame = v4l1_data.active_frame; - Debug( 3, "Captured %d for channel %d", capture_frame, channel ); - - buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame]; - } -#endif // ZM_HAS_V4L1 - } /* prime capture */ + } /* prime capture */ + + if(conversion_type != 0) { - if(conversion_type != 0) { - - Debug( 3, "Performing format conversion" ); - - /* Request a writeable buffer of the target image */ - directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); - if(directbuffer == NULL) { - Error("Failed requesting writeable buffer for the captured image."); - return (-1); - } + Debug( 3, "Performing format conversion" ); + + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } #if HAVE_LIBSWSCALE - if(conversion_type == 1) { - - Debug( 9, "Calling sws_scale to perform the conversion" ); - /* Use swscale to convert the image directly into the shared memory */ - avpicture_fill( (AVPicture *)tmpPicture, directbuffer, imagePixFormat, width, height ); - sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize ); - } -#endif - if(conversion_type == 2) { - - Debug( 9, "Calling the conversion function" ); - /* Call the image conversion function and convert directly into the shared memory */ - (*conversion_fptr)(buffer, directbuffer, pixels); - } - else if(conversion_type == 3) { - - Debug( 9, "Decoding the JPEG image" ); - /* JPEG decoding */ - image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder); - } - - } else { - Debug( 3, "No format conversion performed. Assigning the image" ); - - /* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */ - image.Assign( width, height, colours, subpixelorder, buffer, imagesize); - - } - - return( 0 ); + if(conversion_type == 1) { + + Debug( 9, "Calling sws_scale to perform the conversion" ); + /* Use swscale to convert the image directly into the shared memory */ + avpicture_fill( (AVPicture *)tmpPicture, directbuffer, imagePixFormat, width, height ); + sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize ); + } +#endif + if(conversion_type == 2) { + + Debug( 9, "Calling the conversion function" ); + /* Call the image conversion function and convert directly into the shared memory */ + (*conversion_fptr)(buffer, directbuffer, pixels); + } + else if(conversion_type == 3) { + + Debug( 9, "Decoding the JPEG image" ); + /* JPEG decoding */ + image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder); + } + + } else { + Debug( 3, "No format conversion performed. Assigning the image" ); + + /* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */ + image.Assign( width, height, colours, subpixelorder, buffer, imagesize); + + } + + return( 0 ); } int LocalCamera::PostCapture() { - Debug( 2, "Post-capturing" ); - // Requeue the buffer unless we need to switch or are a duplicate camera on a channel - if ( channel_count > 1 || channel_prime ) - { + Debug( 2, "Post-capturing" ); + // Requeue the buffer unless we need to switch or are a duplicate camera on a channel + if ( channel_count > 1 || channel_prime ) + { #if ZM_HAS_V4L2 - if ( v4l_version == 2 ) + if ( v4l_version == 2 ) + { + if ( channel_count > 1 ) + { + int next_channel = (channel_index+1)%channel_count; + Debug( 3, "Switching video source to %d", channels[next_channel] ); + if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channels[next_channel] ) < 0 ) { - if ( channel_count > 1 ) - { - int next_channel = (channel_index+1)%channel_count; - Debug( 3, "Switching video source to %d", channels[next_channel] ); - if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channels[next_channel] ) < 0 ) - { - Error( "Failed to set camera source %d: %s", channels[next_channel], strerror(errno) ); - return( -1 ); - } - - v4l2_std_id stdId = standards[next_channel]; - if ( vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) - { - Error( "Failed to set video format %d: %s", standards[next_channel], strerror(errno) ); - return( -1 ); - } - } - if ( v4l2_data.bufptr ) { - Debug( 3, "Requeueing buffer %d", v4l2_data.bufptr->index ); - if ( vidioctl( vid_fd, VIDIOC_QBUF, v4l2_data.bufptr ) < 0 ) - { - Error( "Unable to requeue buffer %d: %s", v4l2_data.bufptr->index, strerror(errno) ) - return( -1 ); - } - } else { - Error( "Unable to requeue buffer due to not v4l2_data" ) - } + Error( "Failed to set camera source %d: %s", channels[next_channel], strerror(errno) ); + return( -1 ); } + + v4l2_std_id stdId = standards[next_channel]; + if ( vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) + { + Error( "Failed to set video format %d: %s", standards[next_channel], strerror(errno) ); + return( -1 ); + } + } + if ( v4l2_data.bufptr ) { + Debug( 3, "Requeueing buffer %d", v4l2_data.bufptr->index ); + if ( vidioctl( vid_fd, VIDIOC_QBUF, v4l2_data.bufptr ) < 0 ) + { + Error( "Unable to requeue buffer %d: %s", v4l2_data.bufptr->index, strerror(errno) ) + return( -1 ); + } + } else { + Error( "Unable to requeue buffer due to not v4l2_data" ) + } + } #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - if ( v4l_version == 1 ) + if ( v4l_version == 1 ) + { + if ( channel_count > 1 ) + { + Debug( 3, "Switching video source" ); + int next_channel = (channel_index+1)%channel_count; + struct video_channel vid_src; + memset( &vid_src, 0, sizeof(vid_src) ); + vid_src.channel = channel; + if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) { - if ( channel_count > 1 ) - { - Debug( 3, "Switching video source" ); - int next_channel = (channel_index+1)%channel_count; - struct video_channel vid_src; - memset( &vid_src, 0, sizeof(vid_src) ); - vid_src.channel = channel; - if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) - { - Error( "Failed to get camera source %d: %s", channel, strerror(errno) ); - return(-1); - } - - vid_src.channel = channels[next_channel]; - vid_src.norm = standards[next_channel]; - vid_src.flags = 0; - vid_src.type = VIDEO_TYPE_CAMERA; - if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 ) - { - Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); - return( -1 ); - } - } - Debug( 3, "Requeueing frame %d", v4l1_data.active_frame ); - if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) - { - Error( "Capture failure for frame %d: %s", v4l1_data.active_frame, strerror(errno) ); - return( -1 ); - } - v4l1_data.active_frame = (v4l1_data.active_frame+1)%v4l1_data.frames.frames; + Error( "Failed to get camera source %d: %s", channel, strerror(errno) ); + return(-1); } -#endif // ZM_HAS_V4L1 + + vid_src.channel = channels[next_channel]; + vid_src.norm = standards[next_channel]; + vid_src.flags = 0; + vid_src.type = VIDEO_TYPE_CAMERA; + if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 ) + { + Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); + return( -1 ); + } + } + Debug( 3, "Requeueing frame %d", v4l1_data.active_frame ); + if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) + { + Error( "Capture failure for frame %d: %s", v4l1_data.active_frame, strerror(errno) ); + return( -1 ); + } + v4l1_data.active_frame = (v4l1_data.active_frame+1)%v4l1_data.frames.frames; } - return( 0 ); +#endif // ZM_HAS_V4L1 + } + return( 0 ); } #endif // ZM_HAS_V4L diff --git a/src/zm_local_camera.h b/src/zm_local_camera.h index 016e80150..335c06ce7 100644 --- a/src/zm_local_camera.h +++ b/src/zm_local_camera.h @@ -47,99 +47,99 @@ class LocalCamera : public Camera { protected: #if ZM_HAS_V4L2 - struct V4L2MappedBuffer - { - void *start; - size_t length; - }; + struct V4L2MappedBuffer + { + void *start; + size_t length; + }; - struct V4L2Data - { - v4l2_cropcap cropcap; - v4l2_crop crop; - v4l2_format fmt; - v4l2_requestbuffers reqbufs; - V4L2MappedBuffer *buffers; - v4l2_buffer *bufptr; - }; + struct V4L2Data + { + v4l2_cropcap cropcap; + v4l2_crop crop; + v4l2_format fmt; + v4l2_requestbuffers reqbufs; + V4L2MappedBuffer *buffers; + v4l2_buffer *bufptr; + }; #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - struct V4L1Data - { - int active_frame; - video_mbuf frames; - video_mmap *buffers; - unsigned char *bufptr; - }; + struct V4L1Data + { + int active_frame; + video_mbuf frames; + video_mmap *buffers; + unsigned char *bufptr; + }; #endif // ZM_HAS_V4L1 protected: - std::string device; - int channel; - int standard; - int palette; - bool device_prime; - bool channel_prime; - int channel_index; - unsigned int extras; - - unsigned int conversion_type; /* 0 = no conversion needed, 1 = use libswscale, 2 = zm internal conversion, 3 = jpeg decoding */ - convert_fptr_t conversion_fptr; /* Pointer to conversion function used */ - - uint32_t AutoSelectFormat(int p_colours); + std::string device; + int channel; + int standard; + int palette; + bool device_prime; + bool channel_prime; + int channel_index; + unsigned int extras; + + unsigned int conversion_type; /* 0 = no conversion needed, 1 = use libswscale, 2 = zm internal conversion, 3 = jpeg decoding */ + convert_fptr_t conversion_fptr; /* Pointer to conversion function used */ + + uint32_t AutoSelectFormat(int p_colours); - static int camera_count; - static int channel_count; - static int channels[VIDEO_MAX_FRAME]; - static int standards[VIDEO_MAX_FRAME]; - static int vid_fd; - static int v4l_version; - bool v4l_multi_buffer; - unsigned int v4l_captures_per_frame; + static int camera_count; + static int channel_count; + static int channels[VIDEO_MAX_FRAME]; + static int standards[VIDEO_MAX_FRAME]; + static int vid_fd; + static int v4l_version; + bool v4l_multi_buffer; + unsigned int v4l_captures_per_frame; #if ZM_HAS_V4L2 - static V4L2Data v4l2_data; + static V4L2Data v4l2_data; #endif // ZM_HAS_V4L2 #if ZM_HAS_V4L1 - static V4L1Data v4l1_data; + static V4L1Data v4l1_data; #endif // ZM_HAS_V4L1 #if HAVE_LIBSWSCALE - static AVFrame **capturePictures; - _AVPIXELFORMAT imagePixFormat; - _AVPIXELFORMAT capturePixFormat; - struct SwsContext *imgConversionContext; - AVFrame *tmpPicture; + static AVFrame **capturePictures; + _AVPIXELFORMAT imagePixFormat; + _AVPIXELFORMAT capturePixFormat; + struct SwsContext *imgConversionContext; + AVFrame *tmpPicture; #endif // HAVE_LIBSWSCALE - static LocalCamera *last_camera; + static LocalCamera *last_camera; public: - LocalCamera( int p_id, const std::string &device, int p_channel, int p_format, bool v4lmultibuffer, unsigned int v4lcapturesperframe, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras = 0); - ~LocalCamera(); + LocalCamera( int p_id, const std::string &device, int p_channel, int p_format, bool v4lmultibuffer, unsigned int v4lcapturesperframe, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras = 0); + ~LocalCamera(); - void Initialise(); - void Terminate(); + void Initialise(); + void Terminate(); - const std::string &Device() const { return( device ); } + const std::string &Device() const { return( device ); } - int Channel() const { return( channel ); } - int Standard() const { return( standard ); } - int Palette() const { return( palette ); } - int Extras() const { return( extras ); } + int Channel() const { return( channel ); } + int Standard() const { return( standard ); } + int Palette() const { return( palette ); } + int Extras() const { return( extras ); } - int Brightness( int p_brightness=-1 ); - int Hue( int p_hue=-1 ); - int Colour( int p_colour=-1 ); - int Contrast( int p_contrast=-1 ); + int Brightness( int p_brightness=-1 ); + int Hue( int p_hue=-1 ); + int Colour( int p_colour=-1 ); + int Contrast( int p_contrast=-1 ); - int PrimeCapture(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); - static bool GetCurrentSettings( const char *device, char *output, int version, bool verbose ); + static bool GetCurrentSettings( const char *device, char *output, int version, bool verbose ); }; #endif // ZM_HAS_V4L diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp index f9f62efb1..4d66deee2 100644 --- a/src/zm_logger.cpp +++ b/src/zm_logger.cpp @@ -45,599 +45,599 @@ Logger::IntMap Logger::smSyslogPriorities; #if 0 static void subtractTime( struct timeval * const tp1, struct timeval * const tp2 ) { - tp1->tv_sec -= tp2->tv_sec; - if ( tp1->tv_usec <= tp2->tv_usec ) - { - tp1->tv_sec--; - tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec); - } - else - { - tp1->tv_usec = tp1->tv_usec - tp2->tv_usec; - } + tp1->tv_sec -= tp2->tv_sec; + if ( tp1->tv_usec <= tp2->tv_usec ) + { + tp1->tv_sec--; + tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec); + } + else + { + tp1->tv_usec = tp1->tv_usec - tp2->tv_usec; + } } #endif void Logger::usrHandler( int sig ) { - Logger *logger = fetch(); - if ( sig == SIGUSR1 ) - logger->level( logger->level()+1 ); - else if ( sig == SIGUSR2 ) - logger->level( logger->level()-1 ); - Info( "Logger - Level changed to %d", logger->level() ); + Logger *logger = fetch(); + if ( sig == SIGUSR1 ) + logger->level( logger->level()+1 ); + else if ( sig == SIGUSR2 ) + logger->level( logger->level()-1 ); + Info( "Logger - Level changed to %d", logger->level() ); } Logger::Logger() : - mLevel( INFO ), - mTermLevel( NOLOG ), - mDatabaseLevel( NOLOG ), - mFileLevel( NOLOG ), - mSyslogLevel( NOLOG ), - mEffectiveLevel( NOLOG ), - //mLogPath( config.path_logs ), - //mLogFile( mLogPath+"/"+mId+".log" ), - mDbConnected( false ), - mLogFileFP( NULL ), - mHasTerm( false ), - mFlush( false ) + mLevel( INFO ), + mTermLevel( NOLOG ), + mDatabaseLevel( NOLOG ), + mFileLevel( NOLOG ), + mSyslogLevel( NOLOG ), + mEffectiveLevel( NOLOG ), + //mLogPath( config.path_logs ), + //mLogFile( mLogPath+"/"+mId+".log" ), + mDbConnected( false ), + mLogFileFP( NULL ), + mHasTerm( false ), + mFlush( false ) { - if ( smInstance ) + if ( smInstance ) + { + Panic( "Attempt to create second instance of Logger class" ); + } + + if ( !smInitialised ) + { + smCodes[INFO] = "INF"; + smCodes[WARNING] = "WAR"; + smCodes[ERROR] = "ERR"; + smCodes[FATAL] = "FAT"; + smCodes[PANIC] = "PNC"; + smCodes[NOLOG] = "OFF"; + + smSyslogPriorities[INFO] = LOG_INFO; + smSyslogPriorities[WARNING] = LOG_WARNING; + smSyslogPriorities[ERROR] = LOG_ERR; + smSyslogPriorities[FATAL] = LOG_ERR; + smSyslogPriorities[PANIC] = LOG_ERR; + + char code[4] = ""; + for ( int i = DEBUG1; i <= DEBUG9; i++ ) { - Panic( "Attempt to create second instance of Logger class" ); + snprintf( code, sizeof(code), "DB%d", i ); + smCodes[i] = code; + smSyslogPriorities[i] = LOG_DEBUG; } - if ( !smInitialised ) - { - smCodes[INFO] = "INF"; - smCodes[WARNING] = "WAR"; - smCodes[ERROR] = "ERR"; - smCodes[FATAL] = "FAT"; - smCodes[PANIC] = "PNC"; - smCodes[NOLOG] = "OFF"; + smInitialised = true; + } - smSyslogPriorities[INFO] = LOG_INFO; - smSyslogPriorities[WARNING] = LOG_WARNING; - smSyslogPriorities[ERROR] = LOG_ERR; - smSyslogPriorities[FATAL] = LOG_ERR; - smSyslogPriorities[PANIC] = LOG_ERR; - - char code[4] = ""; - for ( int i = DEBUG1; i <= DEBUG9; i++ ) - { - snprintf( code, sizeof(code), "DB%d", i ); - smCodes[i] = code; - smSyslogPriorities[i] = LOG_DEBUG; - } - - smInitialised = true; - } - - if ( fileno(stderr) && isatty(fileno(stderr)) ) - mHasTerm = true; + if ( fileno(stderr) && isatty(fileno(stderr)) ) + mHasTerm = true; } Logger::~Logger() { - terminate(); + terminate(); } void Logger::initialise( const std::string &id, const Options &options ) { - char *envPtr; + char *envPtr; - if ( !id.empty() ) - this->id( id ); + if ( !id.empty() ) + this->id( id ); - std::string tempLogFile; - if ( options.mLogPath.size() ) + std::string tempLogFile; + if ( options.mLogPath.size() ) + { + mLogPath = options.mLogPath; + tempLogFile = mLogPath+"/"+mId+".log"; + } + if ( options.mLogFile.size() ) + tempLogFile = options.mLogFile; + else + tempLogFile = mLogPath+"/"+mId+".log"; + if ( (envPtr = getTargettedEnv( "LOG_FILE" )) ) + tempLogFile = envPtr; + + Level tempLevel = INFO; + Level tempTermLevel = mTermLevel; + Level tempDatabaseLevel = mDatabaseLevel; + Level tempFileLevel = mFileLevel; + Level tempSyslogLevel = mSyslogLevel; + + if ( options.mTermLevel != NOOPT ) + tempTermLevel = options.mTermLevel; + if ( options.mDatabaseLevel != NOOPT ) + tempDatabaseLevel = options.mDatabaseLevel; + else + tempDatabaseLevel = config.log_level_database >= DEBUG1 ? DEBUG9 : config.log_level_database; + if ( options.mFileLevel != NOOPT ) + tempFileLevel = options.mFileLevel; + else + tempFileLevel = config.log_level_file >= DEBUG1 ? DEBUG9 : config.log_level_file; + if ( options.mSyslogLevel != NOOPT ) + tempSyslogLevel = options.mSyslogLevel; + else + tempSyslogLevel = config.log_level_syslog >= DEBUG1 ? DEBUG9 : config.log_level_syslog; + + // Legacy + if ( (envPtr = getenv( "LOG_PRINT" )) ) + tempTermLevel = atoi(envPtr) ? DEBUG9 : NOLOG; + + if ( (envPtr = getTargettedEnv( "LOG_LEVEL" )) ) + tempLevel = atoi(envPtr); + + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_TERM" )) ) + tempTermLevel = atoi(envPtr); + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_DATABASE" )) ) + tempDatabaseLevel = atoi(envPtr); + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_FILE" )) ) + tempFileLevel = atoi(envPtr); + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_SYSLOG" )) ) + tempSyslogLevel = atoi(envPtr); + + if ( config.log_debug ) + { + StringVector targets = split( config.log_debug_target, "|" ); + for ( unsigned int i = 0; i < targets.size(); i++ ) { - mLogPath = options.mLogPath; - tempLogFile = mLogPath+"/"+mId+".log"; + const std::string &target = targets[i]; + if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "_"+mIdRoot || target == "" ) + { + if ( config.log_debug_level > NOLOG ) + { + tempLevel = config.log_debug_level; + if ( config.log_debug_file[0] ) + { + tempLogFile = config.log_debug_file; + tempFileLevel = tempLevel; + } + } + } } - if ( options.mLogFile.size() ) - tempLogFile = options.mLogFile; - else - tempLogFile = mLogPath+"/"+mId+".log"; - if ( (envPtr = getTargettedEnv( "LOG_FILE" )) ) - tempLogFile = envPtr; + } - Level tempLevel = INFO; - Level tempTermLevel = mTermLevel; - Level tempDatabaseLevel = mDatabaseLevel; - Level tempFileLevel = mFileLevel; - Level tempSyslogLevel = mSyslogLevel; + logFile( tempLogFile ); - if ( options.mTermLevel != NOOPT ) - tempTermLevel = options.mTermLevel; - if ( options.mDatabaseLevel != NOOPT ) - tempDatabaseLevel = options.mDatabaseLevel; - else - tempDatabaseLevel = config.log_level_database >= DEBUG1 ? DEBUG9 : config.log_level_database; - if ( options.mFileLevel != NOOPT ) - tempFileLevel = options.mFileLevel; - else - tempFileLevel = config.log_level_file >= DEBUG1 ? DEBUG9 : config.log_level_file; - if ( options.mSyslogLevel != NOOPT ) - tempSyslogLevel = options.mSyslogLevel; - else - tempSyslogLevel = config.log_level_syslog >= DEBUG1 ? DEBUG9 : config.log_level_syslog; + termLevel( tempTermLevel ); + databaseLevel( tempDatabaseLevel ); + fileLevel( tempFileLevel ); + syslogLevel( tempSyslogLevel ); - // Legacy - if ( (envPtr = getenv( "LOG_PRINT" )) ) - tempTermLevel = atoi(envPtr) ? DEBUG9 : NOLOG; + level( tempLevel ); - if ( (envPtr = getTargettedEnv( "LOG_LEVEL" )) ) - tempLevel = atoi(envPtr); + mFlush = (envPtr = getenv( "LOG_FLUSH")) ? atoi( envPtr ) : false; - if ( (envPtr = getTargettedEnv( "LOG_LEVEL_TERM" )) ) - tempTermLevel = atoi(envPtr); - if ( (envPtr = getTargettedEnv( "LOG_LEVEL_DATABASE" )) ) - tempDatabaseLevel = atoi(envPtr); - if ( (envPtr = getTargettedEnv( "LOG_LEVEL_FILE" )) ) - tempFileLevel = atoi(envPtr); - if ( (envPtr = getTargettedEnv( "LOG_LEVEL_SYSLOG" )) ) - tempSyslogLevel = atoi(envPtr); + //mRuntime = (envPtr = getenv( "LOG_RUNTIME")) ? atoi( envPtr ) : false; - if ( config.log_debug ) + { + struct sigaction action; + memset( &action, 0, sizeof(action) ); + action.sa_handler = usrHandler; + action.sa_flags = SA_RESTART; + + if ( sigaction( SIGUSR1, &action, 0 ) < 0 ) { - StringVector targets = split( config.log_debug_target, "|" ); - for ( unsigned int i = 0; i < targets.size(); i++ ) - { - const std::string &target = targets[i]; - if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "_"+mIdRoot || target == "" ) - { - if ( config.log_debug_level > NOLOG ) - { - tempLevel = config.log_debug_level; - if ( config.log_debug_file[0] ) - { - tempLogFile = config.log_debug_file; - tempFileLevel = tempLevel; - } - } - } - } + Fatal( "sigaction(), error = %s", strerror(errno) ); } - - logFile( tempLogFile ); - - termLevel( tempTermLevel ); - databaseLevel( tempDatabaseLevel ); - fileLevel( tempFileLevel ); - syslogLevel( tempSyslogLevel ); - - level( tempLevel ); - - mFlush = (envPtr = getenv( "LOG_FLUSH")) ? atoi( envPtr ) : false; - - //mRuntime = (envPtr = getenv( "LOG_RUNTIME")) ? atoi( envPtr ) : false; - + if ( sigaction( SIGUSR2, &action, 0 ) < 0) { - struct sigaction action; - memset( &action, 0, sizeof(action) ); - action.sa_handler = usrHandler; - action.sa_flags = SA_RESTART; - - if ( sigaction( SIGUSR1, &action, 0 ) < 0 ) - { - Fatal( "sigaction(), error = %s", strerror(errno) ); - } - if ( sigaction( SIGUSR2, &action, 0 ) < 0) - { - Fatal( "sigaction(), error = %s", strerror(errno) ); - } + Fatal( "sigaction(), error = %s", strerror(errno) ); } + } - mInitialised = true; + mInitialised = true; - Debug( 1, "LogOpts: level=%s/%s, screen=%s, database=%s, logfile=%s->%s, syslog=%s", smCodes[mLevel].c_str(), smCodes[mEffectiveLevel].c_str(), smCodes[mTermLevel].c_str(), smCodes[mDatabaseLevel].c_str(), smCodes[mFileLevel].c_str(), mLogFile.c_str(), smCodes[mSyslogLevel].c_str() ); + Debug( 1, "LogOpts: level=%s/%s, screen=%s, database=%s, logfile=%s->%s, syslog=%s", smCodes[mLevel].c_str(), smCodes[mEffectiveLevel].c_str(), smCodes[mTermLevel].c_str(), smCodes[mDatabaseLevel].c_str(), smCodes[mFileLevel].c_str(), mLogFile.c_str(), smCodes[mSyslogLevel].c_str() ); } void Logger::terminate() { - Debug(1, "Terminating Logger" ); + Debug(1, "Terminating Logger" ); - if ( mFileLevel > NOLOG ) - closeFile(); + if ( mFileLevel > NOLOG ) + closeFile(); - if ( mSyslogLevel > NOLOG ) - closeSyslog(); + if ( mSyslogLevel > NOLOG ) + closeSyslog(); - if ( mDatabaseLevel > NOLOG ) - closeDatabase(); + if ( mDatabaseLevel > NOLOG ) + closeDatabase(); } bool Logger::boolEnv( const std::string &name, bool defaultValue ) { - const char *envPtr = getenv( name.c_str() ); - return( envPtr ? atoi( envPtr ) : defaultValue ); + const char *envPtr = getenv( name.c_str() ); + return( envPtr ? atoi( envPtr ) : defaultValue ); } int Logger::intEnv( const std::string &name, bool defaultValue ) { - const char *envPtr = getenv( name.c_str() ); - return( envPtr ? atoi( envPtr ) : defaultValue ); + const char *envPtr = getenv( name.c_str() ); + return( envPtr ? atoi( envPtr ) : defaultValue ); } std::string Logger::strEnv( const std::string &name, const std::string defaultValue ) { - const char *envPtr = getenv( name.c_str() ); - return( envPtr ? envPtr : defaultValue ); + const char *envPtr = getenv( name.c_str() ); + return( envPtr ? envPtr : defaultValue ); } char *Logger::getTargettedEnv( const std::string &name ) { - char *envPtr = NULL; - std::string envName; + char *envPtr = NULL; + std::string envName; - envName = name+"_"+mId; + envName = name+"_"+mId; + envPtr = getenv( envName.c_str() ); + if ( !envPtr && mId != mIdRoot ) + { + envName = name+"_"+mIdRoot; envPtr = getenv( envName.c_str() ); - if ( !envPtr && mId != mIdRoot ) - { - envName = name+"_"+mIdRoot; - envPtr = getenv( envName.c_str() ); - } - if ( !envPtr ) - envPtr = getenv( name.c_str() ); - return( envPtr ); + } + if ( !envPtr ) + envPtr = getenv( name.c_str() ); + return( envPtr ); } const std::string &Logger::id( const std::string &id ) { - std::string tempId = id; + std::string tempId = id; - size_t pos; - // Remove whitespace - while ( (pos = tempId.find_first_of( " \t" )) != std::string::npos ) + size_t pos; + // Remove whitespace + while ( (pos = tempId.find_first_of( " \t" )) != std::string::npos ) + { + tempId.replace( pos, 1, "" ); + } + // Replace non-alphanum with underscore + while ( (pos = tempId.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" )) != std::string::npos ) + { + tempId.replace( pos, 1, "_" ); + } + if ( mId != tempId ) + { + mId = tempId; + pos = mId.find( '_' ); + if ( pos != std::string::npos ) { - tempId.replace( pos, 1, "" ); + mIdRoot = mId.substr( 0, pos ); + if ( ++pos < mId.size() ) + mIdArgs = mId.substr( pos ); } - // Replace non-alphanum with underscore - while ( (pos = tempId.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" )) != std::string::npos ) - { - tempId.replace( pos, 1, "_" ); - } - if ( mId != tempId ) - { - mId = tempId; - pos = mId.find( '_' ); - if ( pos != std::string::npos ) - { - mIdRoot = mId.substr( 0, pos ); - if ( ++pos < mId.size() ) - mIdArgs = mId.substr( pos ); - } - } - return( mId ); + } + return( mId ); } Logger::Level Logger::level( Logger::Level level ) { - if ( level > NOOPT ) - { - level = limit(level); - if ( mLevel != level ) - mLevel = level; + if ( level > NOOPT ) + { + level = limit(level); + if ( mLevel != level ) + mLevel = level; - mEffectiveLevel = NOLOG; - if ( mTermLevel > mEffectiveLevel ) - mEffectiveLevel = mTermLevel; - if ( mDatabaseLevel > mEffectiveLevel ) - mEffectiveLevel = mDatabaseLevel; - if ( mFileLevel > mEffectiveLevel ) - mEffectiveLevel = mFileLevel; - if ( mSyslogLevel > mEffectiveLevel ) - mEffectiveLevel = mSyslogLevel; - if ( mEffectiveLevel > mLevel) - mEffectiveLevel = mLevel; - } - return( mLevel ); + mEffectiveLevel = NOLOG; + if ( mTermLevel > mEffectiveLevel ) + mEffectiveLevel = mTermLevel; + if ( mDatabaseLevel > mEffectiveLevel ) + mEffectiveLevel = mDatabaseLevel; + if ( mFileLevel > mEffectiveLevel ) + mEffectiveLevel = mFileLevel; + if ( mSyslogLevel > mEffectiveLevel ) + mEffectiveLevel = mSyslogLevel; + if ( mEffectiveLevel > mLevel) + mEffectiveLevel = mLevel; + } + return( mLevel ); } Logger::Level Logger::termLevel( Logger::Level termLevel ) { - if ( termLevel > NOOPT ) - { - if ( !mHasTerm ) - termLevel = NOLOG; - termLevel = limit(termLevel); - if ( mTermLevel != termLevel ) - mTermLevel = termLevel; - } - return( mTermLevel ); + if ( termLevel > NOOPT ) + { + if ( !mHasTerm ) + termLevel = NOLOG; + termLevel = limit(termLevel); + if ( mTermLevel != termLevel ) + mTermLevel = termLevel; + } + return( mTermLevel ); } Logger::Level Logger::databaseLevel( Logger::Level databaseLevel ) { - if ( databaseLevel > NOOPT ) + if ( databaseLevel > NOOPT ) + { + databaseLevel = limit(databaseLevel); + if ( mDatabaseLevel != databaseLevel ) { - databaseLevel = limit(databaseLevel); - if ( mDatabaseLevel != databaseLevel ) + if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) + { + if ( !mDbConnected ) { - if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) + if ( !mysql_init( &mDbConnection ) ) + { + Fatal( "Can't initialise database connection: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + my_bool reconnect = 1; + if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) + Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); + std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":/" ); + if ( colonIndex != std::string::npos ) + { + std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); + std::string dbPort = staticConfig.DB_HOST.substr( colonIndex+1 ); + if ( !mysql_real_connect( &mDbConnection, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, atoi(dbPort.c_str()), 0, 0 ) ) { - if ( !mDbConnected ) - { - if ( !mysql_init( &mDbConnection ) ) - { - Fatal( "Can't initialise database connection: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - my_bool reconnect = 1; - if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) - Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); - std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":/" ); - if ( colonIndex != std::string::npos ) - { - std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); - std::string dbPort = staticConfig.DB_HOST.substr( colonIndex+1 ); - if ( !mysql_real_connect( &mDbConnection, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, atoi(dbPort.c_str()), 0, 0 ) ) - { - Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - } - else - { - if ( !mysql_real_connect( &mDbConnection, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, 0, 0, 0 ) ) - { - Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - } - unsigned long mysqlVersion = mysql_get_server_version( &mDbConnection ); - if ( mysqlVersion < 50019 ) - if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) - Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); - if ( mysql_select_db( &mDbConnection, staticConfig.DB_NAME.c_str() ) ) - { - Fatal( "Can't select database: %s", mysql_error( &mDbConnection ) ); - exit( mysql_errno( &mDbConnection ) ); - } - mDbConnected = true; - } + Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); } - mDatabaseLevel = databaseLevel; + } + else + { + if ( !mysql_real_connect( &mDbConnection, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, 0, 0, 0 ) ) + { + Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + } + unsigned long mysqlVersion = mysql_get_server_version( &mDbConnection ); + if ( mysqlVersion < 50019 ) + if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) + Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); + if ( mysql_select_db( &mDbConnection, staticConfig.DB_NAME.c_str() ) ) + { + Fatal( "Can't select database: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + mDbConnected = true; } + } + mDatabaseLevel = databaseLevel; } - return( mDatabaseLevel ); + } + return( mDatabaseLevel ); } Logger::Level Logger::fileLevel( Logger::Level fileLevel ) { - if ( fileLevel > NOOPT ) + if ( fileLevel > NOOPT ) + { + fileLevel = limit(fileLevel); + if ( mFileLevel != fileLevel ) { - fileLevel = limit(fileLevel); - if ( mFileLevel != fileLevel ) - { - if ( mFileLevel > NOLOG ) - closeFile(); - mFileLevel = fileLevel; - if ( mFileLevel > NOLOG ) - openFile(); - } + if ( mFileLevel > NOLOG ) + closeFile(); + mFileLevel = fileLevel; + if ( mFileLevel > NOLOG ) + openFile(); } - return( mFileLevel ); + } + return( mFileLevel ); } Logger::Level Logger::syslogLevel( Logger::Level syslogLevel ) { - if ( syslogLevel > NOOPT ) + if ( syslogLevel > NOOPT ) + { + syslogLevel = limit(syslogLevel); + if ( mSyslogLevel != syslogLevel ) { - syslogLevel = limit(syslogLevel); - if ( mSyslogLevel != syslogLevel ) - { - if ( mSyslogLevel > NOLOG ) - closeSyslog(); - mSyslogLevel = syslogLevel; - if ( mSyslogLevel > NOLOG ) - openSyslog(); - } + if ( mSyslogLevel > NOLOG ) + closeSyslog(); + mSyslogLevel = syslogLevel; + if ( mSyslogLevel > NOLOG ) + openSyslog(); } - return( mSyslogLevel ); + } + return( mSyslogLevel ); } void Logger::logFile( const std::string &logFile ) { - bool addLogPid = false; - std::string tempLogFile = logFile; - if ( tempLogFile[tempLogFile.length()-1] == '+' ) - { - tempLogFile.resize(tempLogFile.length()-1); - addLogPid = true; - } - if ( addLogPid ) - mLogFile = stringtf( "%s.%05d", tempLogFile.c_str(), getpid() ); - else - mLogFile = tempLogFile; + bool addLogPid = false; + std::string tempLogFile = logFile; + if ( tempLogFile[tempLogFile.length()-1] == '+' ) + { + tempLogFile.resize(tempLogFile.length()-1); + addLogPid = true; + } + if ( addLogPid ) + mLogFile = stringtf( "%s.%05d", tempLogFile.c_str(), getpid() ); + else + mLogFile = tempLogFile; } void Logger::openFile() { - if ( mLogFile.size() && (mLogFileFP = fopen( mLogFile.c_str() ,"w" )) == (FILE *)NULL ) - { - mFileLevel = NOLOG; - Fatal( "fopen() for %s, error = %s", mLogFile.c_str(), strerror(errno) ); - } + if ( mLogFile.size() && (mLogFileFP = fopen( mLogFile.c_str() ,"w" )) == (FILE *)NULL ) + { + mFileLevel = NOLOG; + Fatal( "fopen() for %s, error = %s", mLogFile.c_str(), strerror(errno) ); + } } void Logger::closeFile() { - if ( mLogFileFP ) + if ( mLogFileFP ) + { + fflush( mLogFileFP ); + if ( fclose( mLogFileFP ) < 0 ) { - fflush( mLogFileFP ); - if ( fclose( mLogFileFP ) < 0 ) - { - Fatal( "fclose(), error = %s",strerror(errno) ); - } - mLogFileFP = (FILE *)NULL; + Fatal( "fclose(), error = %s",strerror(errno) ); } + mLogFileFP = (FILE *)NULL; + } } void Logger::closeDatabase() { - if ( mDbConnected ) - { - mysql_close( &mDbConnection ); - mDbConnected = false; - } + if ( mDbConnected ) + { + mysql_close( &mDbConnection ); + mDbConnected = false; + } } void Logger::openSyslog() { - (void) openlog( mId.c_str(), LOG_PID|LOG_NDELAY, LOG_LOCAL1 ); + (void) openlog( mId.c_str(), LOG_PID|LOG_NDELAY, LOG_LOCAL1 ); } void Logger::closeSyslog() { - (void) closelog(); + (void) closelog(); } void Logger::logPrint( bool hex, const char * const filepath, const int line, const int level, const char *fstring, ... ) { - if ( level <= mEffectiveLevel ) + if ( level <= mEffectiveLevel ) + { + char classString[4]; + char timeString[64]; + char logString[8192]; + va_list argPtr; + struct timeval timeVal; + + const char * const file = basename(filepath); + + if ( level < PANIC || level > DEBUG9 ) + Panic( "Invalid logger level %d", level ); + + strncpy( classString, smCodes[level].c_str(), sizeof(classString) ); + + gettimeofday( &timeVal, NULL ); + + #if 0 + if ( logRuntime ) { - char classString[4]; - char timeString[64]; - char logString[8192]; - va_list argPtr; - struct timeval timeVal; + static struct timeval logStart; - const char * const file = basename(filepath); - - if ( level < PANIC || level > DEBUG9 ) - Panic( "Invalid logger level %d", level ); + subtractTime( &timeVal, &logStart ); - strncpy( classString, smCodes[level].c_str(), sizeof(classString) ); + snprintf( timeString, sizeof(timeString), "%ld.%03ld", timeVal.tv_sec, timeVal.tv_usec/1000 ); + } + else + { + #endif + char *timePtr = timeString; + timePtr += strftime( timePtr, sizeof(timeString), "%x %H:%M:%S", localtime(&timeVal.tv_sec) ); + snprintf( timePtr, sizeof(timeString)-(timePtr-timeString), ".%06ld", timeVal.tv_usec ); + #if 0 + } + #endif - gettimeofday( &timeVal, NULL ); - - #if 0 - if ( logRuntime ) - { - static struct timeval logStart; - - subtractTime( &timeVal, &logStart ); - - snprintf( timeString, sizeof(timeString), "%ld.%03ld", timeVal.tv_sec, timeVal.tv_usec/1000 ); - } - else - { - #endif - char *timePtr = timeString; - timePtr += strftime( timePtr, sizeof(timeString), "%x %H:%M:%S", localtime(&timeVal.tv_sec) ); - snprintf( timePtr, sizeof(timeString)-(timePtr-timeString), ".%06ld", timeVal.tv_usec ); - #if 0 - } - #endif - - pid_t tid; + pid_t tid; #ifdef __FreeBSD__ - long lwpid; - thr_self(&lwpid); - tid = lwpid; + long lwpid; + thr_self(&lwpid); + tid = lwpid; - if (tid < 0 ) // Thread/Process id + if (tid < 0 ) // Thread/Process id #else #ifdef HAVE_SYSCALL - #ifdef __FreeBSD_kernel__ - if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id + #ifdef __FreeBSD_kernel__ + if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id - # else - // SOLARIS doesn't have SYS_gettid; don't assume - #ifdef SYS_gettid - if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id - #endif // SYS_gettid - #endif + # else + // SOLARIS doesn't have SYS_gettid; don't assume + #ifdef SYS_gettid + if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id + #endif // SYS_gettid + #endif #endif // HAVE_SYSCALL #endif - tid = getpid(); // Process id + tid = getpid(); // Process id - char *logPtr = logString; - logPtr += snprintf( logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [", - timeString, - mId.c_str(), - tid, - classString, - file, - line - ); - char *syslogStart = logPtr; + char *logPtr = logString; + logPtr += snprintf( logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [", + timeString, + mId.c_str(), + tid, + classString, + file, + line + ); + char *syslogStart = logPtr; - va_start( argPtr, fstring ); - if ( hex ) - { - unsigned char *data = va_arg( argPtr, unsigned char * ); - int len = va_arg( argPtr, int ); - int i; - logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), "%d:", len ); - for ( i = 0; i < len; i++ ) - { - logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), " %02x", data[i] ); - } - } - else - { - logPtr += vsnprintf( logPtr, sizeof(logString)-(logPtr-logString), fstring, argPtr ); - } - va_end(argPtr); - char *syslogEnd = logPtr; - strncpy( logPtr, "]\n", sizeof(logString)-(logPtr-logString) ); - - if ( level <= mTermLevel ) - { - printf( "%s", logString ); - fflush( stdout ); - } - if ( level <= mFileLevel ) - { - fprintf( mLogFileFP, "%s", logString ); - if ( mFlush ) - fflush( mLogFileFP ); - } - *syslogEnd = '\0'; - if ( level <= mDatabaseLevel ) - { - char sql[ZM_SQL_MED_BUFSIZ]; - char escapedString[(strlen(syslogStart)*2)+1]; - - mysql_real_escape_string( &mDbConnection, escapedString, syslogStart, strlen(syslogStart) ); - - snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line ); - if ( mysql_query( &mDbConnection, sql ) ) - { - databaseLevel( NOLOG ); - Error( "Can't insert log entry: %s", mysql_error( &mDbConnection ) ); - } - } - if ( level <= mSyslogLevel ) - { - int priority = smSyslogPriorities[level]; - //priority |= LOG_DAEMON; - syslog( priority, "%s [%s]", classString, syslogStart ); - } - - if ( level <= FATAL ) - { - if ( level <= PANIC ) - abort(); - exit( -1 ); - } + va_start( argPtr, fstring ); + if ( hex ) + { + unsigned char *data = va_arg( argPtr, unsigned char * ); + int len = va_arg( argPtr, int ); + int i; + logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), "%d:", len ); + for ( i = 0; i < len; i++ ) + { + logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), " %02x", data[i] ); + } } + else + { + logPtr += vsnprintf( logPtr, sizeof(logString)-(logPtr-logString), fstring, argPtr ); + } + va_end(argPtr); + char *syslogEnd = logPtr; + strncpy( logPtr, "]\n", sizeof(logString)-(logPtr-logString) ); + + if ( level <= mTermLevel ) + { + printf( "%s", logString ); + fflush( stdout ); + } + if ( level <= mFileLevel ) + { + fprintf( mLogFileFP, "%s", logString ); + if ( mFlush ) + fflush( mLogFileFP ); + } + *syslogEnd = '\0'; + if ( level <= mDatabaseLevel ) + { + char sql[ZM_SQL_MED_BUFSIZ]; + char escapedString[(strlen(syslogStart)*2)+1]; + + mysql_real_escape_string( &mDbConnection, escapedString, syslogStart, strlen(syslogStart) ); + + snprintf( sql, sizeof(sql), "insert into Logs ( TimeKey, Component, ServerId, Pid, Level, Code, Message, File, Line ) values ( %ld.%06ld, '%s', %d, %d, %d, '%s', '%s', '%s', %d )", timeVal.tv_sec, timeVal.tv_usec, mId.c_str(), staticConfig.SERVER_ID, tid, level, classString, escapedString, file, line ); + if ( mysql_query( &mDbConnection, sql ) ) + { + databaseLevel( NOLOG ); + Error( "Can't insert log entry: %s", mysql_error( &mDbConnection ) ); + } + } + if ( level <= mSyslogLevel ) + { + int priority = smSyslogPriorities[level]; + //priority |= LOG_DAEMON; + syslog( priority, "%s [%s]", classString, syslogStart ); + } + + if ( level <= FATAL ) + { + if ( level <= PANIC ) + abort(); + exit( -1 ); + } + } } void logInit( const char *name, const Logger::Options &options ) { - if ( !Logger::smInstance ) - Logger::smInstance = new Logger(); - Logger::Options tempOptions = options; - tempOptions.mLogPath = config.path_logs; - Logger::smInstance->initialise( name, tempOptions ); + if ( !Logger::smInstance ) + Logger::smInstance = new Logger(); + Logger::Options tempOptions = options; + tempOptions.mLogPath = config.path_logs; + Logger::smInstance->initialise( name, tempOptions ); } void logTerm() { - if ( Logger::smInstance ) - delete Logger::smInstance; + if ( Logger::smInstance ) + delete Logger::smInstance; } diff --git a/src/zm_logger.h b/src/zm_logger.h index 8477d61ed..d30396056 100644 --- a/src/zm_logger.h +++ b/src/zm_logger.h @@ -33,190 +33,190 @@ class Logger { public: - enum { - NOOPT=-6, - NOLOG, - PANIC, - FATAL, - ERROR, - WARNING, - INFO, - DEBUG1, - DEBUG2, - DEBUG3, - DEBUG4, - DEBUG5, - DEBUG6, - DEBUG7, - DEBUG8, - DEBUG9 - }; + enum { + NOOPT=-6, + NOLOG, + PANIC, + FATAL, + ERROR, + WARNING, + INFO, + DEBUG1, + DEBUG2, + DEBUG3, + DEBUG4, + DEBUG5, + DEBUG6, + DEBUG7, + DEBUG8, + DEBUG9 + }; - typedef int Level; + typedef int Level; - typedef std::map StringMap; - typedef std::map IntMap; + typedef std::map StringMap; + typedef std::map IntMap; - class Options - { - public: - int mTermLevel; - int mDatabaseLevel; - int mFileLevel; - int mSyslogLevel; + class Options + { + public: + int mTermLevel; + int mDatabaseLevel; + int mFileLevel; + int mSyslogLevel; - std::string mLogPath; - std::string mLogFile; - - public: - Options( Level termLevel=NOOPT, Level databaseLevel=NOOPT, Level fileLevel=NOOPT, Level syslogLevel=NOOPT, const std::string &logPath=".", const std::string &logFile="" ) : - mTermLevel( termLevel ), - mDatabaseLevel( databaseLevel ), - mFileLevel( fileLevel ), - mSyslogLevel( syslogLevel ), - mLogPath( logPath ), - mLogFile( logFile ) - { - } - }; - -private: - static bool smInitialised; - static Logger *smInstance; - - static StringMap smCodes; - static IntMap smSyslogPriorities; - -private: - bool mInitialised; - - std::string mId; - std::string mIdRoot; - std::string mIdArgs; - - Level mLevel; // Level that is currently in operation - Level mTermLevel; // Maximum level output via terminal - Level mDatabaseLevel; // Maximum level output via database - Level mFileLevel; // Maximum level output via file - Level mSyslogLevel; // Maximum level output via syslog - Level mEffectiveLevel; // Level optimised to take account of maxima - - bool mDbConnected; - MYSQL mDbConnection; std::string mLogPath; std::string mLogFile; - FILE *mLogFileFP; - bool mHasTerm; - bool mFlush; + public: + Options( Level termLevel=NOOPT, Level databaseLevel=NOOPT, Level fileLevel=NOOPT, Level syslogLevel=NOOPT, const std::string &logPath=".", const std::string &logFile="" ) : + mTermLevel( termLevel ), + mDatabaseLevel( databaseLevel ), + mFileLevel( fileLevel ), + mSyslogLevel( syslogLevel ), + mLogPath( logPath ), + mLogFile( logFile ) + { + } + }; private: - static void usrHandler( int sig ); + static bool smInitialised; + static Logger *smInstance; -public: - friend void logInit( const char *name, const Options &options ); - friend void logTerm(); - - static Logger *fetch() - { - if ( !smInstance ) - { - smInstance = new Logger(); - Options options; - smInstance->initialise( "undef", options ); - } - return( smInstance ); - } + static StringMap smCodes; + static IntMap smSyslogPriorities; private: - Logger(); - ~Logger(); + bool mInitialised; -public: - void initialise( const std::string &id, const Options &options ); - void terminate(); + std::string mId; + std::string mIdRoot; + std::string mIdArgs; + + Level mLevel; // Level that is currently in operation + Level mTermLevel; // Maximum level output via terminal + Level mDatabaseLevel; // Maximum level output via database + Level mFileLevel; // Maximum level output via file + Level mSyslogLevel; // Maximum level output via syslog + Level mEffectiveLevel; // Level optimised to take account of maxima + + bool mDbConnected; + MYSQL mDbConnection; + std::string mLogPath; + std::string mLogFile; + FILE *mLogFileFP; + + bool mHasTerm; + bool mFlush; private: - int limit( int level ) - { - if ( level > DEBUG9 ) - return( DEBUG9 ); - if ( level < NOLOG ) - return( NOLOG ); - return( level ); - } - - bool boolEnv( const std::string &name, bool defaultValue=false ); - int intEnv( const std::string &name, bool defaultValue=0 ); - std::string strEnv( const std::string &name, const std::string defaultValue="" ); - char *getTargettedEnv( const std::string &name ); - - void loadEnv(); + static void usrHandler( int sig ); public: - const std::string &id() const + friend void logInit( const char *name, const Options &options ); + friend void logTerm(); + + static Logger *fetch() + { + if ( !smInstance ) { - return( mId ); + smInstance = new Logger(); + Options options; + smInstance->initialise( "undef", options ); } - - const std::string &id( const std::string &id ); - - Level level() const - { - return( mLevel ); - } - Level level( Level=NOOPT ); - - bool debugOn() - { - return( mEffectiveLevel >= DEBUG1 ); - } - - Level termLevel( Level=NOOPT ); - Level databaseLevel( Level=NOOPT ); - Level fileLevel( Level=NOOPT ); - Level syslogLevel( Level=NOOPT ); + return( smInstance ); + } private: - void logFile( const std::string &logFile ); - void openFile(); - void closeFile(); - void openSyslog(); - void closeSyslog(); - void closeDatabase(); + Logger(); + ~Logger(); public: - void logPrint( bool hex, const char * const filepath, const int line, const int level, const char *fstring, ... ); + void initialise( const std::string &id, const Options &options ); + void terminate(); + +private: + int limit( int level ) + { + if ( level > DEBUG9 ) + return( DEBUG9 ); + if ( level < NOLOG ) + return( NOLOG ); + return( level ); + } + + bool boolEnv( const std::string &name, bool defaultValue=false ); + int intEnv( const std::string &name, bool defaultValue=0 ); + std::string strEnv( const std::string &name, const std::string defaultValue="" ); + char *getTargettedEnv( const std::string &name ); + + void loadEnv(); + +public: + const std::string &id() const + { + return( mId ); + } + + const std::string &id( const std::string &id ); + + Level level() const + { + return( mLevel ); + } + Level level( Level=NOOPT ); + + bool debugOn() + { + return( mEffectiveLevel >= DEBUG1 ); + } + + Level termLevel( Level=NOOPT ); + Level databaseLevel( Level=NOOPT ); + Level fileLevel( Level=NOOPT ); + Level syslogLevel( Level=NOOPT ); + +private: + void logFile( const std::string &logFile ); + void openFile(); + void closeFile(); + void openSyslog(); + void closeSyslog(); + void closeDatabase(); + +public: + void logPrint( bool hex, const char * const filepath, const int line, const int level, const char *fstring, ... ); }; void logInit( const char *name, const Logger::Options &options=Logger::Options() ); void logTerm(); inline const std::string &logId() { - return( Logger::fetch()->id() ); + return( Logger::fetch()->id() ); } inline Logger::Level logLevel() { - return( Logger::fetch()->level() ); + return( Logger::fetch()->level() ); } inline void logCapLevel( Logger::Level level ) { - Logger::fetch()->level( level ); + Logger::fetch()->level( level ); } inline Logger::Level logDebugging() { - return( Logger::fetch()->debugOn() ); + return( Logger::fetch()->debugOn() ); } #define logPrintf(logLevel,params...) {\ - if ( logLevel <= Logger::fetch()->level() )\ - Logger::fetch()->logPrint( false, __FILE__, __LINE__, logLevel, ##params );\ - } + if ( logLevel <= Logger::fetch()->level() )\ + Logger::fetch()->logPrint( false, __FILE__, __LINE__, logLevel, ##params );\ + } #define logHexdump(logLevel,data,len) {\ - if ( logLevel <= Logger::fetch()->level() )\ - Logger::fetch()->logPrint( true, __FILE__, __LINE__, logLevel, "%p (%d)", data, len );\ - } + if ( logLevel <= Logger::fetch()->level() )\ + Logger::fetch()->logPrint( true, __FILE__, __LINE__, logLevel, "%p (%d)", data, len );\ + } /* Debug compiled out */ #ifndef DBG_OFF @@ -228,19 +228,19 @@ inline Logger::Level logDebugging() #endif /* Standard debug calls */ -#define Info(params...) logPrintf(Logger::INFO,##params) +#define Info(params...) logPrintf(Logger::INFO,##params) #define Warning(params...) logPrintf(Logger::WARNING,##params) -#define Error(params...) logPrintf(Logger::ERROR,##params) -#define Fatal(params...) logPrintf(Logger::FATAL,##params) -#define Panic(params...) logPrintf(Logger::PANIC,##params) -#define Mark() Info("Mark/%s/%d",__FILE__,__LINE__) -#define Log() Info("Log") +#define Error(params...) logPrintf(Logger::ERROR,##params) +#define Fatal(params...) logPrintf(Logger::FATAL,##params) +#define Panic(params...) logPrintf(Logger::PANIC,##params) +#define Mark() Info("Mark/%s/%d",__FILE__,__LINE__) +#define Log() Info("Log") #ifdef __GNUC__ -#define Enter(level) logPrintf(level,("Entering %s",__PRETTY_FUNCTION__)) -#define Exit(level) logPrintf(level,("Exiting %s",__PRETTY_FUNCTION__)) +#define Enter(level) logPrintf(level,("Entering %s",__PRETTY_FUNCTION__)) +#define Exit(level) logPrintf(level,("Exiting %s",__PRETTY_FUNCTION__)) #else -#define Enter(level) -#define Exit(level) +#define Enter(level) +#define Exit(level) #endif #endif // ZM_LOGGER_H diff --git a/src/zm_mem_utils.h b/src/zm_mem_utils.h index 8ce1ceea1..351fa3ac8 100644 --- a/src/zm_mem_utils.h +++ b/src/zm_mem_utils.h @@ -24,138 +24,138 @@ #include "zm.h" inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) { - uint8_t* retptr; + uint8_t* retptr; #if HAVE_POSIX_MEMALIGN - if(posix_memalign((void**)&retptr,reqalignment,reqsize) != 0) - return NULL; - - return retptr; + if(posix_memalign((void**)&retptr,reqalignment,reqsize) != 0) + return NULL; + + return retptr; #else - uint8_t* alloc; - retptr = (uint8_t*)malloc(reqsize+reqalignment+sizeof(void*)); - - if(retptr == NULL) - return NULL; - - alloc = retptr + sizeof(void*); - - if(((long)alloc % reqalignment) != 0) - alloc = alloc + (reqalignment - ((long)alloc % reqalignment)); - - /* Store a pointer before to the start of the block, just before returned aligned memory */ - *(void**)(alloc - sizeof(void*)) = retptr; - - return alloc; + uint8_t* alloc; + retptr = (uint8_t*)malloc(reqsize+reqalignment+sizeof(void*)); + + if(retptr == NULL) + return NULL; + + alloc = retptr + sizeof(void*); + + if(((long)alloc % reqalignment) != 0) + alloc = alloc + (reqalignment - ((long)alloc % reqalignment)); + + /* Store a pointer before to the start of the block, just before returned aligned memory */ + *(void**)(alloc - sizeof(void*)) = retptr; + + return alloc; #endif } inline void zm_freealigned(void* ptr) { #if HAVE_POSIX_MEMALIGN - free(ptr); + free(ptr); #else - /* Start of block is stored before the block if it was allocated by zm_mallocaligned */ - free(*(void**)((uint8_t*)ptr - sizeof(void*))); + /* Start of block is stored before the block if it was allocated by zm_mallocaligned */ + free(*(void**)((uint8_t*)ptr - sizeof(void*))); #endif } inline char *mempbrk( register const char *s, const char *accept, size_t limit ) { - if ( limit <= 0 || !s || !accept || !*accept ) - return( 0 ); - - register unsigned int i,j; - size_t acc_len = strlen( accept ); - - for ( i = 0; i < limit; s++, i++ ) - { - for ( j = 0; j < acc_len; j++ ) - { - if ( *s == accept[j] ) - { - return( (char *)s ); - } - } - } + if ( limit <= 0 || !s || !accept || !*accept ) return( 0 ); + + register unsigned int i,j; + size_t acc_len = strlen( accept ); + + for ( i = 0; i < limit; s++, i++ ) + { + for ( j = 0; j < acc_len; j++ ) + { + if ( *s == accept[j] ) + { + return( (char *)s ); + } + } + } + return( 0 ); } inline char *memstr( register const char *s, const char *n, size_t limit ) { - if ( limit <= 0 || !s || !n ) - return( 0 ); - - if ( !*n ) - return( (char *)s ); - - register unsigned int i,j,k; - size_t n_len = strlen( n ); - - for ( i = 0; i < limit; i++, s++ ) - { - if ( *s != *n ) - continue; - j = 1; - k = 1; - while ( true ) - { - if ( k >= n_len ) - return( (char *)s ); - if ( s[j++] != n[k++] ) - break; - } - } + if ( limit <= 0 || !s || !n ) return( 0 ); + + if ( !*n ) + return( (char *)s ); + + register unsigned int i,j,k; + size_t n_len = strlen( n ); + + for ( i = 0; i < limit; i++, s++ ) + { + if ( *s != *n ) + continue; + j = 1; + k = 1; + while ( true ) + { + if ( k >= n_len ) + return( (char *)s ); + if ( s[j++] != n[k++] ) + break; + } + } + return( 0 ); } inline size_t memspn( register const char *s, const char *accept, size_t limit ) { - if ( limit <= 0 || !s || !accept || !*accept ) - return( 0 ); + if ( limit <= 0 || !s || !accept || !*accept ) + return( 0 ); - register unsigned int i,j; - size_t acc_len = strlen( accept ); + register unsigned int i,j; + size_t acc_len = strlen( accept ); - for ( i = 0; i < limit; s++, i++ ) + for ( i = 0; i < limit; s++, i++ ) + { + register bool found = false; + for ( j = 0; j < acc_len; j++ ) { - register bool found = false; - for ( j = 0; j < acc_len; j++ ) - { - if ( *s == accept[j] ) - { - found = true; - break; - } - } - if ( !found ) - { - return( i ); - } + if ( *s == accept[j] ) + { + found = true; + break; + } } - return( limit ); + if ( !found ) + { + return( i ); + } + } + return( limit ); } inline size_t memcspn( register const char *s, const char *reject, size_t limit ) { - if ( limit <= 0 || !s || !reject ) - return( 0 ); + if ( limit <= 0 || !s || !reject ) + return( 0 ); - if ( !*reject ) - return( limit ); - - register unsigned int i,j; - size_t rej_len = strlen( reject ); - - for ( i = 0; i < limit; s++, i++ ) - { - for ( j = 0; j < rej_len; j++ ) - { - if ( *s == reject[j] ) - { - return( i ); - } - } - } + if ( !*reject ) return( limit ); + + register unsigned int i,j; + size_t rej_len = strlen( reject ); + + for ( i = 0; i < limit; s++, i++ ) + { + for ( j = 0; j < rej_len; j++ ) + { + if ( *s == reject[j] ) + { + return( i ); + } + } + } + return( limit ); } #endif // ZM_MEM_UTILS_H diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index e96997ebc..475fb7b0c 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -62,13 +62,13 @@ //============================================================================= std::vector split(const std::string &s, char delim) { - std::vector elems; - std::stringstream ss(s); - std::string item; - while(std::getline(ss, item, delim)) { - elems.push_back(trimSpaces(item)); - } - return elems; + std::vector elems; + std::stringstream ss(s); + std::string item; + while(std::getline(ss, item, delim)) { + elems.push_back(trimSpaces(item)); + } + return elems; } //============================================================================= @@ -76,2676 +76,2031 @@ std::vector split(const std::string &s, char delim) { Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) { - strncpy( name, p_name, sizeof(name) ); + strncpy( name, p_name, sizeof(name) ); #if ZM_MEM_MAPPED - map_fd = -1; - snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); + map_fd = -1; + snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); #else // ZM_MEM_MAPPED - shm_id = 0; + shm_id = 0; #endif // ZM_MEM_MAPPED - mem_size = 0; - mem_ptr = 0; + mem_size = 0; + mem_ptr = 0; - last_event = 0; - last_state = IDLE; + last_event = 0; + last_state = IDLE; - last_connect_time = 0; - connected = false; + last_connect_time = 0; + connected = false; } Monitor::MonitorLink::~MonitorLink() { - disconnect(); + disconnect(); } bool Monitor::MonitorLink::connect() { - if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) - { - last_connect_time = time( 0 ); + if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) + { + last_connect_time = time( 0 ); - mem_size = sizeof(SharedData) + sizeof(TriggerData); + mem_size = sizeof(SharedData) + sizeof(TriggerData); - Debug( 1, "link.mem.size=%d", mem_size ); + Debug( 1, "link.mem.size=%d", mem_size ); #if ZM_MEM_MAPPED - map_fd = open( mem_file, O_RDWR, (mode_t)0600 ); - if ( map_fd < 0 ) - { - Debug( 3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno) ); - disconnect(); - return( false ); - } - while ( map_fd <= 2 ) { - int new_map_fd = dup(map_fd); - Warning( "Got one of the stdio fds for our mmap handle. map_fd was %d, new one is %d", map_fd, new_map_fd ); - close(map_fd); - map_fd = new_map_fd; - } - - struct stat map_stat; - if ( fstat( map_fd, &map_stat ) < 0 ) - { - Error( "Can't stat linked memory map file %s: %s", mem_file, strerror(errno) ); - disconnect(); - return( false ); - } - - if ( map_stat.st_size == 0 ) - { - Error( "Linked memory map file %s is empty: %s", mem_file, strerror(errno) ); - disconnect(); - return( false ); - } - else if ( map_stat.st_size < mem_size ) - { - Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); - disconnect(); - return( false ); - } - - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); - if ( mem_ptr == MAP_FAILED ) - { - Error( "Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno) ); - disconnect(); - return( false ); - } -#else // ZM_MEM_MAPPED - shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 ); - if ( shm_id < 0 ) - { - Debug( 3, "Can't shmget link memory: %s", strerror(errno) ); - connected = false; - return( false ); - } - mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); - if ( mem_ptr < 0 ) - { - Debug( 3, "Can't shmat link memory: %s", strerror(errno) ); - connected = false; - return( false ); - } -#endif // ZM_MEM_MAPPED - - shared_data = (SharedData *)mem_ptr; - trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); - - if ( !shared_data->valid ) - { - Debug( 3, "Linked memory not initialised by capture daemon" ); - disconnect(); - return( false ); - } - - last_state = shared_data->state; - last_event = shared_data->last_event; - connected = true; - - return( true ); - } - return( false ); -} - -bool Monitor::MonitorLink::disconnect() -{ - if ( connected ) - { - connected = false; - -#if ZM_MEM_MAPPED - if ( mem_ptr > 0 ) - { - msync( mem_ptr, mem_size, MS_ASYNC ); - munmap( mem_ptr, mem_size ); - } - if ( map_fd >= 0 ) - close( map_fd ); - - map_fd = -1; -#else // ZM_MEM_MAPPED - struct shmid_ds shm_data; - if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) - { - Debug( 3, "Can't shmctl: %s", strerror(errno) ); - return( false ); - } - - shm_id = 0; - - if ( shm_data.shm_nattch <= 1 ) - { - if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) - { - Debug( 3, "Can't shmctl: %s", strerror(errno) ); - return( false ); - } - } - - if ( shmdt( mem_ptr ) < 0 ) - { - Debug( 3, "Can't shmdt: %s", strerror(errno) ); - return( false ); - } - -#endif // ZM_MEM_MAPPED - mem_size = 0; - mem_ptr = 0; - } - return( true ); -} - -bool Monitor::MonitorLink::isAlarmed() -{ - if ( !connected ) - { - return( false ); - } - return( shared_data->state == ALARM ); -} - -bool Monitor::MonitorLink::inAlarm() -{ - if ( !connected ) - { - return( false ); - } - return( shared_data->state == ALARM || shared_data->state == ALERT ); -} - -bool Monitor::MonitorLink::hasAlarmed() -{ - if ( shared_data->state == ALARM ) - { - return( true ); - } - else if( shared_data->last_event != (unsigned int)last_event ) - { - last_event = shared_data->last_event; - } - return( false ); -} - -Monitor::Monitor( - int p_id, - const char *p_name, - const unsigned int p_server_id, - int p_function, - bool p_enabled, - const char *p_linked_monitors, - Camera *p_camera, - int p_orientation, - unsigned int p_deinterlacing, - const char *p_event_prefix, - const char *p_label_format, - const Coord &p_label_coord, - int p_label_size, - int p_image_buffer_count, - int p_warmup_count, - int p_pre_event_count, - int p_post_event_count, - int p_stream_replay_buffer, - int p_alarm_frame_count, - int p_section_length, - int p_frame_skip, - int p_motion_frame_skip, - double p_analysis_fps, - unsigned int p_analysis_update_delay, - int p_capture_delay, - int p_alarm_capture_delay, - int p_fps_report_interval, - int p_ref_blend_perc, - int p_alarm_ref_blend_perc, - bool p_track_motion, - Rgb p_signal_check_colour, - bool p_embed_exif, - Purpose p_purpose, - int p_n_zones, - Zone *p_zones[] -) : id( p_id ), - server_id( p_server_id ), - function( (Function)p_function ), - enabled( p_enabled ), - width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), - height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), - orientation( (Orientation)p_orientation ), - deinterlacing( p_deinterlacing ), - label_coord( p_label_coord ), - label_size( p_label_size ), - image_buffer_count( p_image_buffer_count ), - warmup_count( p_warmup_count ), - pre_event_count( p_pre_event_count ), - post_event_count( p_post_event_count ), - stream_replay_buffer( p_stream_replay_buffer ), - section_length( p_section_length ), - frame_skip( p_frame_skip ), - motion_frame_skip( p_motion_frame_skip ), - analysis_fps( p_analysis_fps ), - analysis_update_delay( p_analysis_update_delay ), - capture_delay( p_capture_delay ), - alarm_capture_delay( p_alarm_capture_delay ), - alarm_frame_count( p_alarm_frame_count ), - fps_report_interval( p_fps_report_interval ), - ref_blend_perc( p_ref_blend_perc ), - alarm_ref_blend_perc( p_alarm_ref_blend_perc ), - track_motion( p_track_motion ), - signal_check_colour( p_signal_check_colour ), - embed_exif( p_embed_exif ), - delta_image( width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ), - ref_image( width, height, p_camera->Colours(), p_camera->SubpixelOrder() ), - purpose( p_purpose ), - last_motion_score(0), - camera( p_camera ), - n_zones( p_n_zones ), - zones( p_zones ), - timestamps( 0 ), - images( 0 ), - privacy_bitmask( NULL ) -{ - strncpy( name, p_name, sizeof(name)-1 ); - - strncpy( event_prefix, p_event_prefix, sizeof(event_prefix)-1 ); - strncpy( label_format, p_label_format, sizeof(label_format)-1 ); - - // Change \n to actual line feeds - char *token_ptr = label_format; - const char *token_string = "\n"; - while( ( token_ptr = strstr( token_ptr, token_string ) ) ) - { - if ( *(token_ptr+1) ) - { - *token_ptr = '\n'; - token_ptr++; - strcpy( token_ptr, token_ptr+1 ); - } - else - { - *token_ptr = '\0'; - break; - } - } - - fps = 0.0; - event_count = 0; - image_count = 0; - ready_count = warmup_count; - first_alarm_count = 0; - last_alarm_count = 0; - state = IDLE; - - if ( alarm_frame_count < 1 ) - alarm_frame_count = 1; - else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES ) - alarm_frame_count = MAX_PRE_ALARM_FRAMES; - - auto_resume_time = 0; - - if ( strcmp( config.event_close_mode, "time" ) == 0 ) - event_close_mode = CLOSE_TIME; - else if ( strcmp( config.event_close_mode, "alarm" ) == 0 ) - event_close_mode = CLOSE_ALARM; - else - event_close_mode = CLOSE_IDLE; - - Debug( 1, "monitor purpose=%d", purpose ); - - mem_size = sizeof(SharedData) - + sizeof(TriggerData) - + (image_buffer_count*sizeof(struct timeval)) - + (image_buffer_count*camera->ImageSize()) - + 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */ - - Debug( 1, "mem.size=%d", mem_size ); - mem_ptr = NULL; - - if ( purpose == CAPTURE ) { - this->connect(); - if ( ! mem_ptr ) exit(-1); - memset( mem_ptr, 0, mem_size ); - shared_data->size = sizeof(SharedData); - shared_data->active = enabled; - shared_data->signal = false; - shared_data->state = IDLE; - shared_data->last_write_index = image_buffer_count; - shared_data->last_read_index = image_buffer_count; - shared_data->last_write_time = 0; - shared_data->last_event = 0; - shared_data->action = (Action)0; - shared_data->brightness = -1; - shared_data->hue = -1; - shared_data->colour = -1; - shared_data->contrast = -1; - shared_data->alarm_x = -1; - shared_data->alarm_y = -1; - shared_data->format = camera->SubpixelOrder(); - shared_data->imagesize = camera->ImageSize(); - trigger_data->size = sizeof(TriggerData); - trigger_data->trigger_state = TRIGGER_CANCEL; - trigger_data->trigger_score = 0; - trigger_data->trigger_cause[0] = 0; - trigger_data->trigger_text[0] = 0; - trigger_data->trigger_showtext[0] = 0; - shared_data->valid = true; - } else if ( purpose == ANALYSIS ) { - this->connect(); - if ( ! mem_ptr ) exit(-1); - shared_data->state = IDLE; - shared_data->last_read_time = 0; - shared_data->alarm_x = -1; - shared_data->alarm_y = -1; - } - - if ( ( ! mem_ptr ) || ! shared_data->valid ) - { - if ( purpose != QUERY ) - { - Error( "Shared data not initialised by capture daemon for monitor %s", name ); - exit( -1 ); - } - } - - // Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after.. - if ( !n_zones ) { - Debug( 1, "Monitor %s has no zones, adding one.", name ); - n_zones = 1; - zones = new Zone *[1]; - Coord coords[4] = { Coord( 0, 0 ), Coord( width-1, 0 ), Coord( width-1, height-1 ), Coord( 0, height-1 ) }; - zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Polygon( sizeof(coords)/sizeof(*coords), coords ), RGB_RED, Zone::BLOBS ); - } - start_time = last_fps_time = time( 0 ); - - event = 0; - - Debug( 1, "Monitor %s has function %d", name, function ); - Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d, LBS = %d", name, label_format, label_coord.X(), label_coord.Y(), label_size ); - Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, ARBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion ); - - if ( purpose == ANALYSIS ) - { - static char path[PATH_MAX]; - - strncpy( path, config.dir_events, sizeof(path) ); - - struct stat statbuf; - errno = 0; - stat( path, &statbuf ); - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Error( "Can't make %s: %s", path, strerror(errno)); - } - } - - snprintf( path, sizeof(path), "%s/%d", config.dir_events, id ); - - errno = 0; - stat( path, &statbuf ); - if ( errno == ENOENT || errno == ENOTDIR ) - { - if ( mkdir( path, 0755 ) ) - { - Error( "Can't make %s: %s", path, strerror(errno)); - } - char temp_path[PATH_MAX]; - snprintf( temp_path, sizeof(temp_path), "%d", id ); - if ( chdir( config.dir_events ) < 0 ) - Fatal( "Can't change directory to '%s': %s", config.dir_events, strerror(errno) ); - if ( symlink( temp_path, name ) < 0 ) - Fatal( "Can't symlink '%s' to '%s': %s", temp_path, name, strerror(errno) ); - if ( chdir( ".." ) < 0 ) - Fatal( "Can't change to parent directory: %s", strerror(errno) ); - } - - while( shared_data->last_write_index == (unsigned int)image_buffer_count - && shared_data->last_write_time == 0) - { - Warning( "Waiting for capture daemon" ); - sleep( 1 ); - } - ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize()); - - n_linked_monitors = 0; - linked_monitors = 0; - - adaptive_skip = true; - - ReloadLinkedMonitors( p_linked_monitors ); - } -} - -bool Monitor::connect() { -#if ZM_MEM_MAPPED - snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); - map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); + map_fd = open( mem_file, O_RDWR, (mode_t)0600 ); if ( map_fd < 0 ) - Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + { + Debug( 3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + while ( map_fd <= 2 ) { + int new_map_fd = dup(map_fd); + Warning( "Got one of the stdio fds for our mmap handle. map_fd was %d, new one is %d", map_fd, new_map_fd ); + close(map_fd); + map_fd = new_map_fd; + } struct stat map_stat; if ( fstat( map_fd, &map_stat ) < 0 ) - Fatal( "Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno) ); - if ( map_stat.st_size != mem_size && purpose == CAPTURE ) { - // Allocate the size - if ( ftruncate( map_fd, mem_size ) < 0 ) { - Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); - } - } else if ( map_stat.st_size == 0 ) { - Error( "Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size ); - return false; - } else if ( map_stat.st_size != mem_size ) { - Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); - return false; - } else { -#ifdef MAP_LOCKED - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); - if ( mem_ptr == MAP_FAILED ) { - if ( errno == EAGAIN ) { - Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); -#endif - mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); - Debug( 1, "Mapped file %s (%d bytes) to locked memory, unlocked", mem_file, mem_size ); -#ifdef MAP_LOCKED - } - } -#endif - if ( mem_ptr == MAP_FAILED ) - Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); + { + Error( "Can't stat linked memory map file %s: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + + if ( map_stat.st_size == 0 ) + { + Error( "Linked memory map file %s is empty: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + else if ( map_stat.st_size < mem_size ) + { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + disconnect(); + return( false ); + } + + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) + { + Error( "Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno) ); + disconnect(); + return( false ); } #else // ZM_MEM_MAPPED - shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); - if ( shm_id < 0 ) { - Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); - exit( -1 ); + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 ); + if ( shm_id < 0 ) + { + Debug( 3, "Can't shmget link memory: %s", strerror(errno) ); + connected = false; + return( false ); } mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); if ( mem_ptr < 0 ) { - Error( "Can't shmat: %s", strerror(errno)); - exit( -1 ); + Debug( 3, "Can't shmat link memory: %s", strerror(errno) ); + connected = false; + return( false ); } #endif // ZM_MEM_MAPPED + shared_data = (SharedData *)mem_ptr; trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); - struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData)); - unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); - - if(((unsigned long)shared_images % 16) != 0) { - /* Align images buffer to nearest 16 byte boundary */ - Debug(3,"Aligning shared memory images to the next 16 byte boundary"); - shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16))); - } - image_buffer = new Snapshot[image_buffer_count]; - for ( int i = 0; i < image_buffer_count; i++ ) + + if ( !shared_data->valid ) { - image_buffer[i].timestamp = &(shared_timestamps[i]); - image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); - image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ - } - if ( (deinterlacing & 0xff) == 4) - { - /* Four field motion adaptive deinterlacing in use */ - /* Allocate a buffer for the next image */ - next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); - next_buffer.timestamp = new struct timeval; + Debug( 3, "Linked memory not initialised by capture daemon" ); + disconnect(); + return( false ); } - if ( ( purpose == ANALYSIS ) && analysis_fps ) + last_state = shared_data->state; + last_event = shared_data->last_event; + connected = true; + + return( true ); + } + return( false ); +} + +bool Monitor::MonitorLink::disconnect() +{ + if ( connected ) + { + connected = false; + +#if ZM_MEM_MAPPED + if ( mem_ptr > 0 ) { - // Size of pre event buffer must be greater than pre_event_count - // if alarm_frame_count > 1, because in this case the buffer contains - // alarmed images that must be discarded when event is created - pre_event_buffer_count = pre_event_count + alarm_frame_count - 1; - pre_event_buffer = new Snapshot[pre_event_buffer_count]; - for ( int i = 0; i < pre_event_buffer_count; i++ ) - { - pre_event_buffer[i].timestamp = new struct timeval; - pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); - } + msync( mem_ptr, mem_size, MS_ASYNC ); + munmap( mem_ptr, mem_size ); + } + if ( map_fd >= 0 ) + close( map_fd ); + + map_fd = -1; +#else // ZM_MEM_MAPPED + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); } - return true; + shm_id = 0; + + if ( shm_data.shm_nattch <= 1 ) + { + if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); + } + } + + if ( shmdt( mem_ptr ) < 0 ) + { + Debug( 3, "Can't shmdt: %s", strerror(errno) ); + return( false ); + } + +#endif // ZM_MEM_MAPPED + mem_size = 0; + mem_ptr = 0; + } + return( true ); +} + +bool Monitor::MonitorLink::isAlarmed() +{ + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM ); +} + +bool Monitor::MonitorLink::inAlarm() +{ + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM || shared_data->state == ALERT ); +} + +bool Monitor::MonitorLink::hasAlarmed() +{ + if ( shared_data->state == ALARM ) + { + return( true ); + } + else if( shared_data->last_event != (unsigned int)last_event ) + { + last_event = shared_data->last_event; + } + return( false ); +} + +Monitor::Monitor( + int p_id, + const char *p_name, + const unsigned int p_server_id, + int p_function, + bool p_enabled, + const char *p_linked_monitors, + Camera *p_camera, + int p_orientation, + unsigned int p_deinterlacing, + const char *p_event_prefix, + const char *p_label_format, + const Coord &p_label_coord, + int p_label_size, + int p_image_buffer_count, + int p_warmup_count, + int p_pre_event_count, + int p_post_event_count, + int p_stream_replay_buffer, + int p_alarm_frame_count, + int p_section_length, + int p_frame_skip, + int p_motion_frame_skip, + double p_analysis_fps, + unsigned int p_analysis_update_delay, + int p_capture_delay, + int p_alarm_capture_delay, + int p_fps_report_interval, + int p_ref_blend_perc, + int p_alarm_ref_blend_perc, + bool p_track_motion, + Rgb p_signal_check_colour, + bool p_embed_exif, + Purpose p_purpose, + int p_n_zones, + Zone *p_zones[] +) : id( p_id ), + server_id( p_server_id ), + function( (Function)p_function ), + enabled( p_enabled ), + width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), + height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), + orientation( (Orientation)p_orientation ), + deinterlacing( p_deinterlacing ), + label_coord( p_label_coord ), + label_size( p_label_size ), + image_buffer_count( p_image_buffer_count ), + warmup_count( p_warmup_count ), + pre_event_count( p_pre_event_count ), + post_event_count( p_post_event_count ), + stream_replay_buffer( p_stream_replay_buffer ), + section_length( p_section_length ), + frame_skip( p_frame_skip ), + motion_frame_skip( p_motion_frame_skip ), + analysis_fps( p_analysis_fps ), + analysis_update_delay( p_analysis_update_delay ), + capture_delay( p_capture_delay ), + alarm_capture_delay( p_alarm_capture_delay ), + alarm_frame_count( p_alarm_frame_count ), + fps_report_interval( p_fps_report_interval ), + ref_blend_perc( p_ref_blend_perc ), + alarm_ref_blend_perc( p_alarm_ref_blend_perc ), + track_motion( p_track_motion ), + signal_check_colour( p_signal_check_colour ), + embed_exif( p_embed_exif ), + delta_image( width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ), + ref_image( width, height, p_camera->Colours(), p_camera->SubpixelOrder() ), + purpose( p_purpose ), + last_motion_score(0), + camera( p_camera ), + n_zones( p_n_zones ), + zones( p_zones ), + timestamps( 0 ), + images( 0 ), + privacy_bitmask( NULL ) +{ + strncpy( name, p_name, sizeof(name)-1 ); + + strncpy( event_prefix, p_event_prefix, sizeof(event_prefix)-1 ); + strncpy( label_format, p_label_format, sizeof(label_format)-1 ); + + // Change \n to actual line feeds + char *token_ptr = label_format; + const char *token_string = "\n"; + while( ( token_ptr = strstr( token_ptr, token_string ) ) ) + { + if ( *(token_ptr+1) ) + { + *token_ptr = '\n'; + token_ptr++; + strcpy( token_ptr, token_ptr+1 ); + } + else + { + *token_ptr = '\0'; + break; + } + } + + fps = 0.0; + event_count = 0; + image_count = 0; + ready_count = warmup_count; + first_alarm_count = 0; + last_alarm_count = 0; + state = IDLE; + + if ( alarm_frame_count < 1 ) + alarm_frame_count = 1; + else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES ) + alarm_frame_count = MAX_PRE_ALARM_FRAMES; + + auto_resume_time = 0; + + if ( strcmp( config.event_close_mode, "time" ) == 0 ) + event_close_mode = CLOSE_TIME; + else if ( strcmp( config.event_close_mode, "alarm" ) == 0 ) + event_close_mode = CLOSE_ALARM; + else + event_close_mode = CLOSE_IDLE; + + Debug( 1, "monitor purpose=%d", purpose ); + + mem_size = sizeof(SharedData) + + sizeof(TriggerData) + + (image_buffer_count*sizeof(struct timeval)) + + (image_buffer_count*camera->ImageSize()) + + 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */ + + Debug( 1, "mem.size=%d", mem_size ); + mem_ptr = NULL; + + if ( purpose == CAPTURE ) { + this->connect(); + if ( ! mem_ptr ) exit(-1); + memset( mem_ptr, 0, mem_size ); + shared_data->size = sizeof(SharedData); + shared_data->active = enabled; + shared_data->signal = false; + shared_data->state = IDLE; + shared_data->last_write_index = image_buffer_count; + shared_data->last_read_index = image_buffer_count; + shared_data->last_write_time = 0; + shared_data->last_event = 0; + shared_data->action = (Action)0; + shared_data->brightness = -1; + shared_data->hue = -1; + shared_data->colour = -1; + shared_data->contrast = -1; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + shared_data->format = camera->SubpixelOrder(); + shared_data->imagesize = camera->ImageSize(); + trigger_data->size = sizeof(TriggerData); + trigger_data->trigger_state = TRIGGER_CANCEL; + trigger_data->trigger_score = 0; + trigger_data->trigger_cause[0] = 0; + trigger_data->trigger_text[0] = 0; + trigger_data->trigger_showtext[0] = 0; + shared_data->valid = true; + } else if ( purpose == ANALYSIS ) { + this->connect(); + if ( ! mem_ptr ) exit(-1); + shared_data->state = IDLE; + shared_data->last_read_time = 0; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + } + + if ( ( ! mem_ptr ) || ! shared_data->valid ) + { + if ( purpose != QUERY ) + { + Error( "Shared data not initialised by capture daemon for monitor %s", name ); + exit( -1 ); + } + } + + // Will this not happen every time a monitor is instantiated? Seems like all the calls to the Monitor constructor pass a zero for n_zones, then load zones after.. + if ( !n_zones ) { + Debug( 1, "Monitor %s has no zones, adding one.", name ); + n_zones = 1; + zones = new Zone *[1]; + Coord coords[4] = { Coord( 0, 0 ), Coord( width-1, 0 ), Coord( width-1, height-1 ), Coord( 0, height-1 ) }; + zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Polygon( sizeof(coords)/sizeof(*coords), coords ), RGB_RED, Zone::BLOBS ); + } + start_time = last_fps_time = time( 0 ); + + event = 0; + + Debug( 1, "Monitor %s has function %d", name, function ); + Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d, LBS = %d", name, label_format, label_coord.X(), label_coord.Y(), label_size ); + Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, ARBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, alarm_ref_blend_perc, track_motion ); + + if ( purpose == ANALYSIS ) + { + static char path[PATH_MAX]; + + strncpy( path, config.dir_events, sizeof(path) ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + } + + snprintf( path, sizeof(path), "%s/%d", config.dir_events, id ); + + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + char temp_path[PATH_MAX]; + snprintf( temp_path, sizeof(temp_path), "%d", id ); + if ( chdir( config.dir_events ) < 0 ) + Fatal( "Can't change directory to '%s': %s", config.dir_events, strerror(errno) ); + if ( symlink( temp_path, name ) < 0 ) + Fatal( "Can't symlink '%s' to '%s': %s", temp_path, name, strerror(errno) ); + if ( chdir( ".." ) < 0 ) + Fatal( "Can't change to parent directory: %s", strerror(errno) ); + } + + while( shared_data->last_write_index == (unsigned int)image_buffer_count + && shared_data->last_write_time == 0) + { + Warning( "Waiting for capture daemon" ); + sleep( 1 ); + } + ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize()); + + n_linked_monitors = 0; + linked_monitors = 0; + + adaptive_skip = true; + + ReloadLinkedMonitors( p_linked_monitors ); + } +} + +bool Monitor::connect() { +#if ZM_MEM_MAPPED + snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); + map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); + if ( map_fd < 0 ) + Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + + struct stat map_stat; + if ( fstat( map_fd, &map_stat ) < 0 ) + Fatal( "Can't stat memory map file %s: %s, is the zmc process for this monitor running?", mem_file, strerror(errno) ); + if ( map_stat.st_size != mem_size && purpose == CAPTURE ) { + // Allocate the size + if ( ftruncate( map_fd, mem_size ) < 0 ) { + Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); + } + } else if ( map_stat.st_size == 0 ) { + Error( "Got empty memory map file size %ld, is the zmc process for this monitor running?", map_stat.st_size, mem_size ); + return false; + } else if ( map_stat.st_size != mem_size ) { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + return false; + } else { +#ifdef MAP_LOCKED + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) { + if ( errno == EAGAIN ) { + Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); +#endif + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + Debug( 1, "Mapped file %s (%d bytes) to locked memory, unlocked", mem_file, mem_size ); +#ifdef MAP_LOCKED + } + } +#endif + if ( mem_ptr == MAP_FAILED ) + Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); + } +#else // ZM_MEM_MAPPED + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); + if ( shm_id < 0 ) { + Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); + exit( -1 ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Error( "Can't shmat: %s", strerror(errno)); + exit( -1 ); + } +#endif // ZM_MEM_MAPPED + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData)); + unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); + + if(((unsigned long)shared_images % 16) != 0) { + /* Align images buffer to nearest 16 byte boundary */ + Debug(3,"Aligning shared memory images to the next 16 byte boundary"); + shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16))); + } + image_buffer = new Snapshot[image_buffer_count]; + for ( int i = 0; i < image_buffer_count; i++ ) + { + image_buffer[i].timestamp = &(shared_timestamps[i]); + image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); + image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ + } + if ( (deinterlacing & 0xff) == 4) + { + /* Four field motion adaptive deinterlacing in use */ + /* Allocate a buffer for the next image */ + next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); + next_buffer.timestamp = new struct timeval; + } + + if ( ( purpose == ANALYSIS ) && analysis_fps ) + { + // Size of pre event buffer must be greater than pre_event_count + // if alarm_frame_count > 1, because in this case the buffer contains + // alarmed images that must be discarded when event is created + pre_event_buffer_count = pre_event_count + alarm_frame_count - 1; + pre_event_buffer = new Snapshot[pre_event_buffer_count]; + for ( int i = 0; i < pre_event_buffer_count; i++ ) + { + pre_event_buffer[i].timestamp = new struct timeval; + pre_event_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); + } + } + + return true; } Monitor::~Monitor() { - if ( timestamps ) { - delete[] timestamps; - timestamps = 0; - } - if ( images ) { - delete[] images; - images = 0; - } - if ( privacy_bitmask ) { - delete[] privacy_bitmask; - privacy_bitmask = NULL; - } - if ( mem_ptr ) { - if ( event ) - Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); - closeEvent(); - - if ( (deinterlacing & 0xff) == 4) - { - delete next_buffer.image; - delete next_buffer.timestamp; - } - for ( int i = 0; i < image_buffer_count; i++ ) - { - delete image_buffer[i].image; - } - delete[] image_buffer; - } // end if mem_ptr - - for ( int i = 0; i < n_zones; i++ ) - { - delete zones[i]; + if ( timestamps ) { + delete[] timestamps; + timestamps = 0; + } + if ( images ) { + delete[] images; + images = 0; + } + if ( privacy_bitmask ) { + delete[] privacy_bitmask; + privacy_bitmask = NULL; } - delete[] zones; + if ( mem_ptr ) { + if ( event ) + Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); + closeEvent(); - delete camera; + if ( (deinterlacing & 0xff) == 4) + { + delete next_buffer.image; + delete next_buffer.timestamp; + } + for ( int i = 0; i < image_buffer_count; i++ ) + { + delete image_buffer[i].image; + } + delete[] image_buffer; + } // end if mem_ptr - if ( mem_ptr ) { - if ( purpose == ANALYSIS ) - { - shared_data->state = state = IDLE; - shared_data->last_read_index = image_buffer_count; - shared_data->last_read_time = 0; + for ( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; - if ( analysis_fps ) - { - for ( int i = 0; i < pre_event_buffer_count; i++ ) - { - delete pre_event_buffer[i].image; - delete pre_event_buffer[i].timestamp; - } - delete[] pre_event_buffer; - } - } - else if ( purpose == CAPTURE ) - { - shared_data->valid = false; - memset( mem_ptr, 0, mem_size ); - } + delete camera; + + if ( mem_ptr ) { + if ( purpose == ANALYSIS ) + { + shared_data->state = state = IDLE; + shared_data->last_read_index = image_buffer_count; + shared_data->last_read_time = 0; + + if ( analysis_fps ) + { + for ( int i = 0; i < pre_event_buffer_count; i++ ) + { + delete pre_event_buffer[i].image; + delete pre_event_buffer[i].timestamp; + } + delete[] pre_event_buffer; + } + } + else if ( purpose == CAPTURE ) + { + shared_data->valid = false; + memset( mem_ptr, 0, mem_size ); + } #if ZM_MEM_MAPPED - if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 ) - Error( "Can't msync: %s", strerror(errno) ); - if ( munmap( mem_ptr, mem_size ) < 0 ) - Fatal( "Can't munmap: %s", strerror(errno) ); - close( map_fd ); + if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 ) + Error( "Can't msync: %s", strerror(errno) ); + if ( munmap( mem_ptr, mem_size ) < 0 ) + Fatal( "Can't munmap: %s", strerror(errno) ); + close( map_fd ); #else // ZM_MEM_MAPPED - struct shmid_ds shm_data; - if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) { - Error( "Can't shmctl: %s", strerror(errno) ); - exit( -1 ); - } - if ( shm_data.shm_nattch <= 1 ) { - if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) { - Error( "Can't shmctl: %s", strerror(errno) ); - exit( -1 ); - } - } + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) { + Error( "Can't shmctl: %s", strerror(errno) ); + exit( -1 ); + } + if ( shm_data.shm_nattch <= 1 ) { + if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) { + Error( "Can't shmctl: %s", strerror(errno) ); + exit( -1 ); + } + } #endif // ZM_MEM_MAPPED - } // end if mem_ptr + } // end if mem_ptr } void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) { - for ( int i = 0; i < n_zones; i++ ) - delete zones[i]; - delete[] zones; - n_zones = p_n_zones; - zones = p_zones; + for ( int i = 0; i < n_zones; i++ ) + delete zones[i]; + delete[] zones; + n_zones = p_n_zones; + zones = p_zones; } void Monitor::AddPrivacyBitmask( Zone *p_zones[] ) { - if ( privacy_bitmask ) - delete[] privacy_bitmask; - privacy_bitmask = NULL; - Image *privacy_image = NULL; + if ( privacy_bitmask ) + delete[] privacy_bitmask; + privacy_bitmask = NULL; + Image *privacy_image = NULL; - for ( int i = 0; i < n_zones; i++ ) + for ( int i = 0; i < n_zones; i++ ) + { + if ( p_zones[i]->IsPrivacy() ) { - if ( p_zones[i]->IsPrivacy() ) - { - if ( !privacy_image ) - { - privacy_image = new Image( width, height, 1, ZM_SUBPIX_ORDER_NONE); - privacy_image->Clear(); - } - privacy_image->Fill( 0xff, p_zones[i]->GetPolygon() ); - privacy_image->Outline( 0xff, p_zones[i]->GetPolygon() ); - } - } // end foreach zone - if ( privacy_image ) - privacy_bitmask = privacy_image->Buffer(); + if ( !privacy_image ) + { + privacy_image = new Image( width, height, 1, ZM_SUBPIX_ORDER_NONE); + privacy_image->Clear(); + } + privacy_image->Fill( 0xff, p_zones[i]->GetPolygon() ); + privacy_image->Outline( 0xff, p_zones[i]->GetPolygon() ); + } + } // end foreach zone + if ( privacy_image ) + privacy_bitmask = privacy_image->Buffer(); } Monitor::State Monitor::GetState() const { - return( (State)shared_data->state ); + return( (State)shared_data->state ); } int Monitor::GetImage( int index, int scale ) { - if ( index < 0 || index > image_buffer_count ) - { - index = shared_data->last_write_index; + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } + + if ( index != image_buffer_count ) + { + Image *image; + // If we are going to be modifying the snapshot before writing, then we need to copy it + if ( ( scale != ZM_SCALE_BASE ) || ( !config.timestamp_on_capture ) ) { + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + alarm_image.Assign( *snap_image ); + + + //write_image.Assign( *snap_image ); + + if ( scale != ZM_SCALE_BASE ) { + alarm_image.Scale( scale ); + } + + if ( !config.timestamp_on_capture ) { + TimestampImage( &alarm_image, snap->timestamp ); + } + image = &alarm_image; + } else { + image = image_buffer[index].image; } - if ( index != image_buffer_count ) - { - Image *image; - // If we are going to be modifying the snapshot before writing, then we need to copy it - if ( ( scale != ZM_SCALE_BASE ) || ( !config.timestamp_on_capture ) ) { - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; - - alarm_image.Assign( *snap_image ); - - - //write_image.Assign( *snap_image ); - - if ( scale != ZM_SCALE_BASE ) { - alarm_image.Scale( scale ); - } - - if ( !config.timestamp_on_capture ) { - TimestampImage( &alarm_image, snap->timestamp ); - } - image = &alarm_image; - } else { - image = image_buffer[index].image; - } - - static char filename[PATH_MAX]; - snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); - image->WriteJpeg( filename ); - } - else - { - Error( "Unable to generate image, no images in buffer" ); - } - return( 0 ); + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); + image->WriteJpeg( filename ); + } + else + { + Error( "Unable to generate image, no images in buffer" ); + } + return( 0 ); } struct timeval Monitor::GetTimestamp( int index ) const { - if ( index < 0 || index > image_buffer_count ) - { - index = shared_data->last_write_index; - } + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } - if ( index != image_buffer_count ) - { - Snapshot *snap = &image_buffer[index]; + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; - return( *(snap->timestamp) ); - } - else - { - static struct timeval null_tv = { 0, 0 }; + return( *(snap->timestamp) ); + } + else + { + static struct timeval null_tv = { 0, 0 }; - return( null_tv ); - } + return( null_tv ); + } } unsigned int Monitor::GetLastReadIndex() const { - return( shared_data->last_read_index!=(unsigned int)image_buffer_count?shared_data->last_read_index:-1 ); + return( shared_data->last_read_index!=(unsigned int)image_buffer_count?shared_data->last_read_index:-1 ); } unsigned int Monitor::GetLastWriteIndex() const { - return( shared_data->last_write_index!=(unsigned int)image_buffer_count?shared_data->last_write_index:-1 ); + return( shared_data->last_write_index!=(unsigned int)image_buffer_count?shared_data->last_write_index:-1 ); } unsigned int Monitor::GetLastEvent() const { - return( shared_data->last_event ); + return( shared_data->last_event ); } double Monitor::GetFPS() const { - int index1 = shared_data->last_write_index; - if ( index1 == image_buffer_count ) - { - return( 0.0 ); - } - Snapshot *snap1 = &image_buffer[index1]; - if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) - { - return( 0.0 ); - } - struct timeval time1 = *snap1->timestamp; + int index1 = shared_data->last_write_index; + if ( index1 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap1 = &image_buffer[index1]; + if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) + { + return( 0.0 ); + } + struct timeval time1 = *snap1->timestamp; - int image_count = image_buffer_count; - int index2 = (index1+1)%image_buffer_count; - if ( index2 == image_buffer_count ) + int image_count = image_buffer_count; + int index2 = (index1+1)%image_buffer_count; + if ( index2 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap2 = &image_buffer[index2]; + while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) + { + if ( index1 == index2 ) { - return( 0.0 ); + return( 0.0 ); } - Snapshot *snap2 = &image_buffer[index2]; - while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) - { - if ( index1 == index2 ) - { - return( 0.0 ); - } - index2 = (index2+1)%image_buffer_count; - snap2 = &image_buffer[index2]; - image_count--; - } - struct timeval time2 = *snap2->timestamp; + index2 = (index2+1)%image_buffer_count; + snap2 = &image_buffer[index2]; + image_count--; + } + struct timeval time2 = *snap2->timestamp; - double time_diff = tvDiffSec( time2, time1 ); + double time_diff = tvDiffSec( time2, time1 ); - double curr_fps = image_count/time_diff; + double curr_fps = image_count/time_diff; - if ( curr_fps < 0.0 ) - { - //Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count ); - return( 0.0 ); - } - return( curr_fps ); + if ( curr_fps < 0.0 ) + { + //Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count ); + return( 0.0 ); + } + return( curr_fps ); } useconds_t Monitor::GetAnalysisRate() { - double capturing_fps = GetFPS(); - if ( !analysis_fps ) - { - return( 0 ); - } - else if ( analysis_fps > capturing_fps ) - { - Warning( "Analysis fps (%.2f) is greater than capturing fps (%.2f)", analysis_fps, capturing_fps ); - return( 0 ); - } - else - { - return( ( 1000000 / analysis_fps ) - ( 1000000 / capturing_fps ) ); - } + double capturing_fps = GetFPS(); + if ( !analysis_fps ) + { + return( 0 ); + } + else if ( analysis_fps > capturing_fps ) + { + Warning( "Analysis fps (%.2f) is greater than capturing fps (%.2f)", analysis_fps, capturing_fps ); + return( 0 ); + } + else + { + return( ( 1000000 / analysis_fps ) - ( 1000000 / capturing_fps ) ); + } } void Monitor::UpdateAdaptiveSkip() { - if ( config.opt_adaptive_skip ) + if ( config.opt_adaptive_skip ) + { + double capturing_fps = GetFPS(); + if ( adaptive_skip && analysis_fps && ( analysis_fps < capturing_fps ) ) { - double capturing_fps = GetFPS(); - if ( adaptive_skip && analysis_fps && ( analysis_fps < capturing_fps ) ) - { - Info( "Analysis fps (%.2f) is lower than capturing fps (%.2f), disabling adaptive skip feature", analysis_fps, capturing_fps ); - adaptive_skip = false; - } - else if ( !adaptive_skip && ( !analysis_fps || ( analysis_fps >= capturing_fps ) ) ) - { - Info( "Enabling adaptive skip feature" ); - adaptive_skip = true; - } + Info( "Analysis fps (%.2f) is lower than capturing fps (%.2f), disabling adaptive skip feature", analysis_fps, capturing_fps ); + adaptive_skip = false; } - else + else if ( !adaptive_skip && ( !analysis_fps || ( analysis_fps >= capturing_fps ) ) ) { - adaptive_skip = false; + Info( "Enabling adaptive skip feature" ); + adaptive_skip = true; } + } + else + { + adaptive_skip = false; + } } void Monitor::ForceAlarmOn( int force_score, const char *force_cause, const char *force_text ) { - trigger_data->trigger_state = TRIGGER_ON; - trigger_data->trigger_score = force_score; - strncpy( trigger_data->trigger_cause, force_cause, sizeof(trigger_data->trigger_cause) ); - strncpy( trigger_data->trigger_text, force_text, sizeof(trigger_data->trigger_text) ); + trigger_data->trigger_state = TRIGGER_ON; + trigger_data->trigger_score = force_score; + strncpy( trigger_data->trigger_cause, force_cause, sizeof(trigger_data->trigger_cause) ); + strncpy( trigger_data->trigger_text, force_text, sizeof(trigger_data->trigger_text) ); } void Monitor::ForceAlarmOff() { - trigger_data->trigger_state = TRIGGER_OFF; + trigger_data->trigger_state = TRIGGER_OFF; } void Monitor::CancelForced() { - trigger_data->trigger_state = TRIGGER_CANCEL; + trigger_data->trigger_state = TRIGGER_CANCEL; } void Monitor::actionReload() { - shared_data->action |= RELOAD; + shared_data->action |= RELOAD; } void Monitor::actionEnable() { - shared_data->action |= RELOAD; + shared_data->action |= RELOAD; - static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "update Monitors set Enabled = 1 where Id = '%d'", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 1 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } void Monitor::actionDisable() { - shared_data->action |= RELOAD; + shared_data->action |= RELOAD; - static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "update Monitors set Enabled = 0 where Id = '%d'", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 0 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } void Monitor::actionSuspend() { - shared_data->action |= SUSPEND; + shared_data->action |= SUSPEND; } void Monitor::actionResume() { - shared_data->action |= RESUME; + shared_data->action |= RESUME; } int Monitor::actionBrightness( int p_brightness ) { - if ( purpose != CAPTURE ) + if ( purpose != CAPTURE ) + { + if ( p_brightness >= 0 ) { - if ( p_brightness >= 0 ) - { - shared_data->brightness = p_brightness; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to set brightness" ); - return( -1 ); - } - } - } + shared_data->brightness = p_brightness; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); else { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to get brightness" ); - return( -1 ); - } - } + Warning( "Timed out waiting to set brightness" ); + return( -1 ); } - return( shared_data->brightness ); + } } - return( camera->Brightness( p_brightness ) ); + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get brightness" ); + return( -1 ); + } + } + } + return( shared_data->brightness ); + } + return( camera->Brightness( p_brightness ) ); } int Monitor::actionContrast( int p_contrast ) { - if ( purpose != CAPTURE ) + if ( purpose != CAPTURE ) + { + if ( p_contrast >= 0 ) { - if ( p_contrast >= 0 ) - { - shared_data->contrast = p_contrast; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to set contrast" ); - return( -1 ); - } - } - } + shared_data->contrast = p_contrast; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); else { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to get contrast" ); - return( -1 ); - } - } + Warning( "Timed out waiting to set contrast" ); + return( -1 ); } - return( shared_data->contrast ); + } } - return( camera->Contrast( p_contrast ) ); + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get contrast" ); + return( -1 ); + } + } + } + return( shared_data->contrast ); + } + return( camera->Contrast( p_contrast ) ); } int Monitor::actionHue( int p_hue ) { - if ( purpose != CAPTURE ) + if ( purpose != CAPTURE ) + { + if ( p_hue >= 0 ) { - if ( p_hue >= 0 ) - { - shared_data->hue = p_hue; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to set hue" ); - return( -1 ); - } - } - } + shared_data->hue = p_hue; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); else { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to get hue" ); - return( -1 ); - } - } + Warning( "Timed out waiting to set hue" ); + return( -1 ); } - return( shared_data->hue ); + } } - return( camera->Hue( p_hue ) ); + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get hue" ); + return( -1 ); + } + } + } + return( shared_data->hue ); + } + return( camera->Hue( p_hue ) ); } int Monitor::actionColour( int p_colour ) { - if ( purpose != CAPTURE ) + if ( purpose != CAPTURE ) + { + if ( p_colour >= 0 ) { - if ( p_colour >= 0 ) - { - shared_data->colour = p_colour; - shared_data->action |= SET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & SET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to set colour" ); - return( -1 ); - } - } - } + shared_data->colour = p_colour; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); else { - shared_data->action |= GET_SETTINGS; - int wait_loops = 10; - while ( shared_data->action & GET_SETTINGS ) - { - if ( wait_loops-- ) - usleep( 100000 ); - else - { - Warning( "Timed out waiting to get colour" ); - return( -1 ); - } - } + Warning( "Timed out waiting to set colour" ); + return( -1 ); } - return( shared_data->colour ); + } } - return( camera->Colour( p_colour ) ); + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get colour" ); + return( -1 ); + } + } + } + return( shared_data->colour ); + } + return( camera->Colour( p_colour ) ); } void Monitor::DumpZoneImage( const char *zone_string ) { - int exclude_id = 0; - int extra_colour = 0; - Polygon extra_zone; + int exclude_id = 0; + int extra_colour = 0; + Polygon extra_zone; - if ( zone_string ) + if ( zone_string ) + { + if ( !Zone::ParseZoneString( zone_string, exclude_id, extra_colour, extra_zone ) ) { - if ( !Zone::ParseZoneString( zone_string, exclude_id, extra_colour, extra_zone ) ) - { - Error( "Failed to parse zone string, ignoring" ); - } + Error( "Failed to parse zone string, ignoring" ); } + } - int index = shared_data->last_write_index; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + int index = shared_data->last_write_index; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - Image zone_image( *snap_image ); - if(zone_image.Colours() == ZM_COLOUR_GRAY8) { - zone_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); - } - - for( int i = 0; i < n_zones; i++ ) + Image zone_image( *snap_image ); + if(zone_image.Colours() == ZM_COLOUR_GRAY8) { + zone_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + } + + for( int i = 0; i < n_zones; i++ ) + { + if ( exclude_id && (!extra_colour || extra_zone.getNumCoords()) && zones[i]->Id() == exclude_id ) + continue; + + Rgb colour; + if ( exclude_id && !extra_zone.getNumCoords() && zones[i]->Id() == exclude_id ) { - if ( exclude_id && (!extra_colour || extra_zone.getNumCoords()) && zones[i]->Id() == exclude_id ) - continue; - - Rgb colour; - if ( exclude_id && !extra_zone.getNumCoords() && zones[i]->Id() == exclude_id ) - { - colour = extra_colour; - } - else - { - if ( zones[i]->IsActive() ) - { - colour = RGB_RED; - } - else if ( zones[i]->IsInclusive() ) - { - colour = RGB_ORANGE; - } - else if ( zones[i]->IsExclusive() ) - { - colour = RGB_PURPLE; - } - else if ( zones[i]->IsPreclusive() ) - { - colour = RGB_BLUE; - } - else - { - colour = RGB_WHITE; - } - } - zone_image.Fill( colour, 2, zones[i]->GetPolygon() ); - zone_image.Outline( colour, zones[i]->GetPolygon() ); + colour = extra_colour; } - - if ( extra_zone.getNumCoords() ) + else { - zone_image.Fill( extra_colour, 2, extra_zone ); - zone_image.Outline( extra_colour, extra_zone ); + if ( zones[i]->IsActive() ) + { + colour = RGB_RED; + } + else if ( zones[i]->IsInclusive() ) + { + colour = RGB_ORANGE; + } + else if ( zones[i]->IsExclusive() ) + { + colour = RGB_PURPLE; + } + else if ( zones[i]->IsPreclusive() ) + { + colour = RGB_BLUE; + } + else + { + colour = RGB_WHITE; + } } + zone_image.Fill( colour, 2, zones[i]->GetPolygon() ); + zone_image.Outline( colour, zones[i]->GetPolygon() ); + } - static char filename[PATH_MAX]; - snprintf( filename, sizeof(filename), "Zones%d.jpg", id ); - zone_image.WriteJpeg( filename ); + if ( extra_zone.getNumCoords() ) + { + zone_image.Fill( extra_colour, 2, extra_zone ); + zone_image.Outline( extra_colour, extra_zone ); + } + + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Zones%d.jpg", id ); + zone_image.WriteJpeg( filename ); } void Monitor::DumpImage( Image *dump_image ) const { - if ( image_count && !(image_count%10) ) - { - static char filename[PATH_MAX]; - static char new_filename[PATH_MAX]; - snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); - snprintf( new_filename, sizeof(new_filename), "Monitor%d-new.jpg", id ); - dump_image->WriteJpeg( new_filename ); - rename( new_filename, filename ); - } + if ( image_count && !(image_count%10) ) + { + static char filename[PATH_MAX]; + static char new_filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); + snprintf( new_filename, sizeof(new_filename), "Monitor%d-new.jpg", id ); + dump_image->WriteJpeg( new_filename ); + rename( new_filename, filename ); + } } bool Monitor::CheckSignal( const Image *image ) { - static bool static_undef = true; - /* RGB24 colors */ - static uint8_t red_val; - static uint8_t green_val; - static uint8_t blue_val; - static uint8_t grayscale_val; /* 8bit grayscale color */ - static Rgb colour_val; /* RGB32 color */ - static int usedsubpixorder; + static bool static_undef = true; + /* RGB24 colors */ + static uint8_t red_val; + static uint8_t green_val; + static uint8_t blue_val; + static uint8_t grayscale_val; /* 8bit grayscale color */ + static Rgb colour_val; /* RGB32 color */ + static int usedsubpixorder; - if ( config.signal_check_points > 0 ) + if ( config.signal_check_points > 0 ) + { + if ( static_undef ) { - if ( static_undef ) - { - static_undef = false; - usedsubpixorder = camera->SubpixelOrder(); - colour_val = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ - colour_val = rgb_convert(colour_val, usedsubpixorder); - red_val = RED_VAL_BGRA(signal_check_colour); - green_val = GREEN_VAL_BGRA(signal_check_colour); - blue_val = BLUE_VAL_BGRA(signal_check_colour); - grayscale_val = signal_check_colour & 0xff; /* Clear all bytes but lowest byte */ - } - - const uint8_t *buffer = image->Buffer(); - int pixels = image->Pixels(); - int width = image->Width(); - int colours = image->Colours(); - - int index = 0; - for ( int i = 0; i < config.signal_check_points; i++ ) - { - while( true ) - { - index = (int)(((long long)rand()*(long long)(pixels-1))/RAND_MAX); - if ( !config.timestamp_on_capture || !label_format[0] ) - break; - // Avoid sampling the rows with timestamp in - if ( index < (label_coord.Y()*width) || index >= (label_coord.Y()+Image::LINE_HEIGHT)*width ) - break; - } - - if(colours == ZM_COLOUR_GRAY8) { - if ( *(buffer+index) != grayscale_val ) - return true; - - } else if(colours == ZM_COLOUR_RGB24) { - const uint8_t *ptr = buffer+(index*colours); - - if ( usedsubpixorder == ZM_SUBPIX_ORDER_BGR) { - if ( (RED_PTR_BGRA(ptr) != red_val) || (GREEN_PTR_BGRA(ptr) != green_val) || (BLUE_PTR_BGRA(ptr) != blue_val) ) - return true; - } else { - /* Assume RGB */ - if ( (RED_PTR_RGBA(ptr) != red_val) || (GREEN_PTR_RGBA(ptr) != green_val) || (BLUE_PTR_RGBA(ptr) != blue_val) ) - return true; - } - - } else if(colours == ZM_COLOUR_RGB32) { - if ( usedsubpixorder == ZM_SUBPIX_ORDER_ARGB || usedsubpixorder == ZM_SUBPIX_ORDER_ABGR) { - if ( ARGB_ABGR_ZEROALPHA(*(((const Rgb*)buffer)+index)) != ARGB_ABGR_ZEROALPHA(colour_val) ) - return true; - } else { - /* Assume RGBA or BGRA */ - if ( RGBA_BGRA_ZEROALPHA(*(((const Rgb*)buffer)+index)) != RGBA_BGRA_ZEROALPHA(colour_val) ) - return true; - } - } - - } - return( false ); + static_undef = false; + usedsubpixorder = camera->SubpixelOrder(); + colour_val = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ + colour_val = rgb_convert(colour_val, usedsubpixorder); + red_val = RED_VAL_BGRA(signal_check_colour); + green_val = GREEN_VAL_BGRA(signal_check_colour); + blue_val = BLUE_VAL_BGRA(signal_check_colour); + grayscale_val = signal_check_colour & 0xff; /* Clear all bytes but lowest byte */ } - return( true ); + + const uint8_t *buffer = image->Buffer(); + int pixels = image->Pixels(); + int width = image->Width(); + int colours = image->Colours(); + + int index = 0; + for ( int i = 0; i < config.signal_check_points; i++ ) + { + while( true ) + { + index = (int)(((long long)rand()*(long long)(pixels-1))/RAND_MAX); + if ( !config.timestamp_on_capture || !label_format[0] ) + break; + // Avoid sampling the rows with timestamp in + if ( index < (label_coord.Y()*width) || index >= (label_coord.Y()+Image::LINE_HEIGHT)*width ) + break; + } + + if(colours == ZM_COLOUR_GRAY8) { + if ( *(buffer+index) != grayscale_val ) + return true; + + } else if(colours == ZM_COLOUR_RGB24) { + const uint8_t *ptr = buffer+(index*colours); + + if ( usedsubpixorder == ZM_SUBPIX_ORDER_BGR) { + if ( (RED_PTR_BGRA(ptr) != red_val) || (GREEN_PTR_BGRA(ptr) != green_val) || (BLUE_PTR_BGRA(ptr) != blue_val) ) + return true; + } else { + /* Assume RGB */ + if ( (RED_PTR_RGBA(ptr) != red_val) || (GREEN_PTR_RGBA(ptr) != green_val) || (BLUE_PTR_RGBA(ptr) != blue_val) ) + return true; + } + + } else if(colours == ZM_COLOUR_RGB32) { + if ( usedsubpixorder == ZM_SUBPIX_ORDER_ARGB || usedsubpixorder == ZM_SUBPIX_ORDER_ABGR) { + if ( ARGB_ABGR_ZEROALPHA(*(((const Rgb*)buffer)+index)) != ARGB_ABGR_ZEROALPHA(colour_val) ) + return true; + } else { + /* Assume RGBA or BGRA */ + if ( RGBA_BGRA_ZEROALPHA(*(((const Rgb*)buffer)+index)) != RGBA_BGRA_ZEROALPHA(colour_val) ) + return true; + } + } + + } + return( false ); + } + return( true ); } bool Monitor::Analyse() { - if ( shared_data->last_read_index == shared_data->last_write_index ) + if ( shared_data->last_read_index == shared_data->last_write_index ) + { + return( false ); + } + + struct timeval now; + gettimeofday( &now, NULL ); + + if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + { + fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); + Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps ); + last_fps_time = now.tv_sec; + } + + int index; + if ( adaptive_skip ) + { + int read_margin = shared_data->last_read_index - shared_data->last_write_index; + if ( read_margin < 0 ) read_margin += image_buffer_count; + + int step = 1; + if ( read_margin > 0 ) { - return( false ); + step = (9*image_buffer_count)/(5*read_margin); } - struct timeval now; - gettimeofday( &now, NULL ); + int pending_frames = shared_data->last_write_index - shared_data->last_read_index; + if ( pending_frames < 0 ) pending_frames += image_buffer_count; - if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step ); + if ( step <= pending_frames ) { - fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); - Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps ); - last_fps_time = now.tv_sec; - } - - int index; - if ( adaptive_skip ) - { - int read_margin = shared_data->last_read_index - shared_data->last_write_index; - if ( read_margin < 0 ) read_margin += image_buffer_count; - - int step = 1; - if ( read_margin > 0 ) - { - step = (9*image_buffer_count)/(5*read_margin); - } - - int pending_frames = shared_data->last_write_index - shared_data->last_read_index; - if ( pending_frames < 0 ) pending_frames += image_buffer_count; - - Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step ); - if ( step <= pending_frames ) - { - index = (shared_data->last_read_index+step)%image_buffer_count; - } - else - { - if ( pending_frames ) - { - Warning( "Approaching buffer overrun, consider slowing capture, simplifying analysis or increasing ring buffer size" ); - } - index = shared_data->last_write_index%image_buffer_count; - } + index = (shared_data->last_read_index+step)%image_buffer_count; } else { - index = shared_data->last_write_index%image_buffer_count; + if ( pending_frames ) + { + Warning( "Approaching buffer overrun, consider slowing capture, simplifying analysis or increasing ring buffer size" ); + } + index = shared_data->last_write_index%image_buffer_count; } + } + else + { + index = shared_data->last_write_index%image_buffer_count; + } - Snapshot *snap = &image_buffer[index]; - struct timeval *timestamp = snap->timestamp; - Image *snap_image = snap->image; + Snapshot *snap = &image_buffer[index]; + struct timeval *timestamp = snap->timestamp; + Image *snap_image = snap->image; - if ( shared_data->action ) + if ( shared_data->action ) + { + if ( shared_data->action & RELOAD ) { - if ( shared_data->action & RELOAD ) - { - Info( "Received reload indication at count %d", image_count ); - shared_data->action &= ~RELOAD; - Reload(); - } - if ( shared_data->action & SUSPEND ) - { - if ( Active() ) - { - Info( "Received suspend indication at count %d", image_count ); - shared_data->active = false; - //closeEvent(); - } - if ( config.max_suspend_time ) - { - auto_resume_time = now.tv_sec + config.max_suspend_time; - } - shared_data->action &= ~SUSPEND; - } - if ( shared_data->action & RESUME ) - { - if ( Enabled() && !Active() ) - { - Info( "Received resume indication at count %d", image_count ); - shared_data->active = true; - ref_image = *snap_image; - ready_count = image_count+(warmup_count/2); - shared_data->alarm_x = shared_data->alarm_y = -1; - } - shared_data->action &= ~RESUME; - } + Info( "Received reload indication at count %d", image_count ); + shared_data->action &= ~RELOAD; + Reload(); } - if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) + if ( shared_data->action & SUSPEND ) { - Info( "Auto resuming at count %d", image_count ); + if ( Active() ) + { + Info( "Received suspend indication at count %d", image_count ); + shared_data->active = false; + //closeEvent(); + } + if ( config.max_suspend_time ) + { + auto_resume_time = now.tv_sec + config.max_suspend_time; + } + shared_data->action &= ~SUSPEND; + } + if ( shared_data->action & RESUME ) + { + if ( Enabled() && !Active() ) + { + Info( "Received resume indication at count %d", image_count ); shared_data->active = true; ref_image = *snap_image; ready_count = image_count+(warmup_count/2); - auto_resume_time = 0; + shared_data->alarm_x = shared_data->alarm_y = -1; + } + shared_data->action &= ~RESUME; } + } + if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) + { + Info( "Auto resuming at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + auto_resume_time = 0; + } - static bool static_undef = true; - static int last_section_mod = 0; - static bool last_signal; + static bool static_undef = true; + static int last_section_mod = 0; + static bool last_signal; - if ( static_undef ) + if ( static_undef ) + { + static_undef = false; + timestamps = new struct timeval *[pre_event_count]; + images = new Image *[pre_event_count]; + last_signal = shared_data->signal; + } + + if ( Enabled() ) + { + bool signal = shared_data->signal; + bool signal_change = (signal != last_signal); + if ( trigger_data->trigger_state != TRIGGER_OFF ) { - static_undef = false; - timestamps = new struct timeval *[pre_event_count]; - images = new Image *[pre_event_count]; - last_signal = shared_data->signal; - } + unsigned int score = 0; + if ( Ready() ) + { + std::string cause; + Event::StringSetMap noteSetMap; - if ( Enabled() ) - { - bool signal = shared_data->signal; - bool signal_change = (signal != last_signal); - if ( trigger_data->trigger_state != TRIGGER_OFF ) + if ( trigger_data->trigger_state == TRIGGER_ON ) { - unsigned int score = 0; - if ( Ready() ) + score += trigger_data->trigger_score; + if ( !event ) + { + if ( cause.length() ) + cause += ", "; + cause += trigger_data->trigger_cause; + } + Event::StringSet noteSet; + noteSet.insert( trigger_data->trigger_text ); + noteSetMap[trigger_data->trigger_cause] = noteSet; + } + if ( signal_change ) + { + const char *signalText; + if ( !signal ) + signalText = "Lost"; + else + { + signalText = "Reacquired"; + score += 100; + } + Warning( "%s: %s", SIGNAL_CAUSE, signalText ); + if ( event && !signal ) + { + Info( "%s: %03d - Closing event %d, signal loss", name, image_count, event->Id() ); + closeEvent(); + last_section_mod = 0; + } + if ( !event ) + { + if ( cause.length() ) + cause += ", "; + cause += SIGNAL_CAUSE; + } + Event::StringSet noteSet; + noteSet.insert( signalText ); + noteSetMap[SIGNAL_CAUSE] = noteSet; + shared_data->state = state = IDLE; + shared_data->active = signal; + ref_image = *snap_image; + } + else if ( signal && Active() && (function == MODECT || function == MOCORD) ) + { + Event::StringSet zoneSet; + int motion_score = last_motion_score; + if ( !(image_count % (motion_frame_skip+1) ) ) + { + // Get new score. + motion_score = last_motion_score = DetectMotion( *snap_image, zoneSet ); + } + //int motion_score = DetectBlack( *snap_image, zoneSet ); + if ( motion_score ) + { + if ( !event ) { - std::string cause; - Event::StringSetMap noteSetMap; + score += motion_score; + if ( cause.length() ) + cause += ", "; + cause += MOTION_CAUSE; + } + else + { + score += motion_score; + } + noteSetMap[MOTION_CAUSE] = zoneSet; - if ( trigger_data->trigger_state == TRIGGER_ON ) + } + shared_data->active = signal; + } + if ( (!signal_change && signal) && n_linked_monitors > 0 ) + { + bool first_link = true; + Event::StringSet noteSet; + for ( int i = 0; i < n_linked_monitors; i++ ) + { + if ( linked_monitors[i]->isConnected() ) + { + if ( linked_monitors[i]->hasAlarmed() ) + { + if ( !event ) { - score += trigger_data->trigger_score; - if ( !event ) - { - if ( cause.length() ) - cause += ", "; - cause += trigger_data->trigger_cause; - } - Event::StringSet noteSet; - noteSet.insert( trigger_data->trigger_text ); - noteSetMap[trigger_data->trigger_cause] = noteSet; + if ( first_link ) + { + if ( cause.length() ) + cause += ", "; + cause += LINKED_CAUSE; + first_link = false; + } } - if ( signal_change ) + noteSet.insert( linked_monitors[i]->Name() ); + score += 50; + } + } + else + { + linked_monitors[i]->connect(); + } + } + if ( noteSet.size() > 0 ) + noteSetMap[LINKED_CAUSE] = noteSet; + } + if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) + { + if ( event ) + { + int section_mod = timestamp->tv_sec%section_length; + if ( section_mod < last_section_mod ) + { + if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) + { + if ( state == TAPE ) { - const char *signalText; - if ( !signal ) - signalText = "Lost"; - else - { - signalText = "Reacquired"; - score += 100; - } - Warning( "%s: %s", SIGNAL_CAUSE, signalText ); - if ( event && !signal ) - { - Info( "%s: %03d - Closing event %d, signal loss", name, image_count, event->Id() ); - closeEvent(); - last_section_mod = 0; - } - if ( !event ) - { - if ( cause.length() ) - cause += ", "; - cause += SIGNAL_CAUSE; - } - Event::StringSet noteSet; - noteSet.insert( signalText ); - noteSetMap[SIGNAL_CAUSE] = noteSet; - shared_data->state = state = IDLE; - shared_data->active = signal; - ref_image = *snap_image; + shared_data->state = state = IDLE; + Info( "%s: %03d - Closing event %d, section end", name, image_count, event->Id() ) } - else if ( signal && Active() && (function == MODECT || function == MOCORD) ) - { - Event::StringSet zoneSet; - int motion_score = last_motion_score; - if ( !(image_count % (motion_frame_skip+1) ) ) - { - // Get new score. - motion_score = last_motion_score = DetectMotion( *snap_image, zoneSet ); - } - //int motion_score = DetectBlack( *snap_image, zoneSet ); - if ( motion_score ) - { - if ( !event ) - { - score += motion_score; - if ( cause.length() ) - cause += ", "; - cause += MOTION_CAUSE; - } - else - { - score += motion_score; - } - noteSetMap[MOTION_CAUSE] = zoneSet; + else + Info( "%s: %03d - Closing event %d, section end forced ", name, image_count, event->Id() ); + closeEvent(); + last_section_mod = 0; + } + } + else + { + last_section_mod = section_mod; + } + } + if ( !event ) + { - } - shared_data->active = signal; + // Create event + event = new Event( this, *timestamp, "Continuous", noteSetMap ); + shared_data->last_event = event->Id(); + + Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() ); + + /* To prevent cancelling out an existing alert\prealarm\alarm state */ + if ( state == IDLE ) + { + shared_data->state = state = TAPE; + } + + //if ( config.overlap_timed_events ) + if ( false ) + { + int pre_index; + int pre_event_images = pre_event_count; + + if ( analysis_fps ) + { + // If analysis fps is set, + // compute the index for pre event images in the dedicated buffer + pre_index = image_count%pre_event_buffer_count; + + // Seek forward the next filled slot in to the buffer (oldest data) + // from the current position + while ( pre_event_images && !pre_event_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index + 1)%pre_event_buffer_count; + // Slot is empty, removing image from counter + pre_event_images--; } - if ( (!signal_change && signal) && n_linked_monitors > 0 ) + } + else + { + // If analysis fps is not set (analysis performed at capturing framerate), + // compute the index for pre event images in the capturing buffer + pre_index = ((index + image_buffer_count) - pre_event_count)%image_buffer_count; + + // Seek forward the next filled slot in to the buffer (oldest data) + // from the current position + while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) { - bool first_link = true; - Event::StringSet noteSet; - for ( int i = 0; i < n_linked_monitors; i++ ) - { - if ( linked_monitors[i]->isConnected() ) - { - if ( linked_monitors[i]->hasAlarmed() ) - { - if ( !event ) - { - if ( first_link ) - { - if ( cause.length() ) - cause += ", "; - cause += LINKED_CAUSE; - first_link = false; - } - } - noteSet.insert( linked_monitors[i]->Name() ); - score += 50; - } - } - else - { - linked_monitors[i]->connect(); - } - } - if ( noteSet.size() > 0 ) - noteSetMap[LINKED_CAUSE] = noteSet; + pre_index = (pre_index + 1)%image_buffer_count; + // Slot is empty, removing image from counter + pre_event_images--; } - if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) + } + + if ( pre_event_images ) + { + if ( analysis_fps ) + for ( int i = 0; i < pre_event_images; i++ ) + { + timestamps[i] = pre_event_buffer[pre_index].timestamp; + images[i] = pre_event_buffer[pre_index].image; + pre_index = (pre_index + 1)%pre_event_buffer_count; + } + else + for ( int i = 0; i < pre_event_images; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; + pre_index = (pre_index + 1)%image_buffer_count; + } + + event->AddFrames( pre_event_images, images, timestamps ); + } + } + } + } + if ( score ) + { + if ( (state == IDLE || state == TAPE || state == PREALARM ) ) + { + if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) + { + Info( "%s: %03d - Gone into alarm state", name, image_count ); + shared_data->state = state = ALARM; + if ( signal_change || (function != MOCORD && state != ALERT) ) + { + int pre_index; + int pre_event_images = pre_event_count; + + if ( analysis_fps ) { - if ( event ) - { - int section_mod = timestamp->tv_sec%section_length; - if ( section_mod < last_section_mod ) - { - if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) - { - if ( state == TAPE ) - { - shared_data->state = state = IDLE; - Info( "%s: %03d - Closing event %d, section end", name, image_count, event->Id() ) - } - else - Info( "%s: %03d - Closing event %d, section end forced ", name, image_count, event->Id() ); - closeEvent(); - last_section_mod = 0; - } - } - else - { - last_section_mod = section_mod; - } - } - if ( !event ) - { + // If analysis fps is set, + // compute the index for pre event images in the dedicated buffer + pre_index = image_count%pre_event_buffer_count; - // Create event - event = new Event( this, *timestamp, "Continuous", noteSetMap ); - shared_data->last_event = event->Id(); + // Seek forward the next filled slot in to the buffer (oldest data) + // from the current position + while ( pre_event_images && !pre_event_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index + 1)%pre_event_buffer_count; + // Slot is empty, removing image from counter + pre_event_images--; + } - Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() ); - - /* To prevent cancelling out an existing alert\prealarm\alarm state */ - if ( state == IDLE ) - { - shared_data->state = state = TAPE; - } - - //if ( config.overlap_timed_events ) - if ( false ) - { - int pre_index; - int pre_event_images = pre_event_count; - - if ( analysis_fps ) - { - // If analysis fps is set, - // compute the index for pre event images in the dedicated buffer - pre_index = image_count%pre_event_buffer_count; - - // Seek forward the next filled slot in to the buffer (oldest data) - // from the current position - while ( pre_event_images && !pre_event_buffer[pre_index].timestamp->tv_sec ) - { - pre_index = (pre_index + 1)%pre_event_buffer_count; - // Slot is empty, removing image from counter - pre_event_images--; - } - } - else - { - // If analysis fps is not set (analysis performed at capturing framerate), - // compute the index for pre event images in the capturing buffer - pre_index = ((index + image_buffer_count) - pre_event_count)%image_buffer_count; - - // Seek forward the next filled slot in to the buffer (oldest data) - // from the current position - while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) - { - pre_index = (pre_index + 1)%image_buffer_count; - // Slot is empty, removing image from counter - pre_event_images--; - } - } - - if ( pre_event_images ) - { - if ( analysis_fps ) - for ( int i = 0; i < pre_event_images; i++ ) - { - timestamps[i] = pre_event_buffer[pre_index].timestamp; - images[i] = pre_event_buffer[pre_index].image; - pre_index = (pre_index + 1)%pre_event_buffer_count; - } - else - for ( int i = 0; i < pre_event_images; i++ ) - { - timestamps[i] = image_buffer[pre_index].timestamp; - images[i] = image_buffer[pre_index].image; - pre_index = (pre_index + 1)%image_buffer_count; - } - - event->AddFrames( pre_event_images, images, timestamps ); - } - } - } - } - if ( score ) - { - if ( (state == IDLE || state == TAPE || state == PREALARM ) ) - { - if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) - { - Info( "%s: %03d - Gone into alarm state", name, image_count ); - shared_data->state = state = ALARM; - if ( signal_change || (function != MOCORD && state != ALERT) ) - { - int pre_index; - int pre_event_images = pre_event_count; - - if ( analysis_fps ) - { - // If analysis fps is set, - // compute the index for pre event images in the dedicated buffer - pre_index = image_count%pre_event_buffer_count; - - // Seek forward the next filled slot in to the buffer (oldest data) - // from the current position - while ( pre_event_images && !pre_event_buffer[pre_index].timestamp->tv_sec ) - { - pre_index = (pre_index + 1)%pre_event_buffer_count; - // Slot is empty, removing image from counter - pre_event_images--; - } - - event = new Event( this, *(pre_event_buffer[pre_index].timestamp), cause, noteSetMap ); - } - else - { - // If analysis fps is not set (analysis performed at capturing framerate), - // compute the index for pre event images in the capturing buffer - if ( alarm_frame_count > 1 ) - pre_index = ((index + image_buffer_count) - ((alarm_frame_count - 1) + pre_event_count))%image_buffer_count; - else - pre_index = ((index + image_buffer_count) - pre_event_count)%image_buffer_count; - - // Seek forward the next filled slot in to the buffer (oldest data) - // from the current position - while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) - { - pre_index = (pre_index + 1)%image_buffer_count; - // Slot is empty, removing image from counter - pre_event_images--; - } - - event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap ); - } - shared_data->last_event = event->Id(); - - Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() ); - - if ( pre_event_images ) - { - if ( analysis_fps ) - for ( int i = 0; i < pre_event_images; i++ ) - { - timestamps[i] = pre_event_buffer[pre_index].timestamp; - images[i] = pre_event_buffer[pre_index].image; - pre_index = (pre_index + 1)%pre_event_buffer_count; - } - else - for ( int i = 0; i < pre_event_images; i++ ) - { - timestamps[i] = image_buffer[pre_index].timestamp; - images[i] = image_buffer[pre_index].image; - pre_index = (pre_index + 1)%image_buffer_count; - } - - event->AddFrames( pre_event_images, images, timestamps ); - } - if ( alarm_frame_count ) - { - event->SavePreAlarmFrames(); - } - } - } - else if ( state != PREALARM ) - { - Info( "%s: %03d - Gone into prealarm state", name, image_count ); - shared_data->state = state = PREALARM; - } - } - else if ( state == ALERT ) - { - Info( "%s: %03d - Gone back into alarm state", name, image_count ); - shared_data->state = state = ALARM; - } - last_alarm_count = image_count; + event = new Event( this, *(pre_event_buffer[pre_index].timestamp), cause, noteSetMap ); } else { - if ( state == ALARM ) - { - Info( "%s: %03d - Gone into alert state", name, image_count ); - shared_data->state = state = ALERT; - } - else if ( state == ALERT ) - { - if ( image_count-last_alarm_count > post_event_count ) - { - Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() ); - //if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE ) - if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) - { - shared_data->state = state = IDLE; - Info( "%s: %03d - Closing event %d, alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); - closeEvent(); - } - else - { - shared_data->state = state = TAPE; - } - } - } - if ( state == PREALARM ) - { - if ( function != MOCORD ) - { - shared_data->state = state = IDLE; - } - else - { - shared_data->state = state = TAPE; - } - } - if ( Event::PreAlarmCount() ) - Event::EmptyPreAlarmFrames(); + // If analysis fps is not set (analysis performed at capturing framerate), + // compute the index for pre event images in the capturing buffer + if ( alarm_frame_count > 1 ) + pre_index = ((index + image_buffer_count) - ((alarm_frame_count - 1) + pre_event_count))%image_buffer_count; + else + pre_index = ((index + image_buffer_count) - pre_event_count)%image_buffer_count; + + // Seek forward the next filled slot in to the buffer (oldest data) + // from the current position + while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index + 1)%image_buffer_count; + // Slot is empty, removing image from counter + pre_event_images--; + } + + event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap ); } - if ( state != IDLE ) + shared_data->last_event = event->Id(); + + Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() ); + + if ( pre_event_images ) { - if ( state == PREALARM || state == ALARM ) + if ( analysis_fps ) + for ( int i = 0; i < pre_event_images; i++ ) { - if ( config.create_analysis_images ) - { - bool got_anal_image = false; - alarm_image.Assign( *snap_image ); - for( int i = 0; i < n_zones; i++ ) - { - if ( zones[i]->Alarmed() ) - { - if ( zones[i]->AlarmImage() ) - { - alarm_image.Overlay( *(zones[i]->AlarmImage()) ); - got_anal_image = true; - } - if ( config.record_event_stats && state == ALARM ) - { - zones[i]->RecordStats( event ); - } - } - } - if ( got_anal_image ) - { - if ( state == PREALARM ) - Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image ); - else - event->AddFrame( snap_image, *timestamp, score, &alarm_image ); - } - else - { - if ( state == PREALARM ) - Event::AddPreAlarmFrame( snap_image, *timestamp, score ); - else - event->AddFrame( snap_image, *timestamp, score ); - } - } - else - { - for( int i = 0; i < n_zones; i++ ) - { - if ( zones[i]->Alarmed() ) - { - if ( config.record_event_stats && state == ALARM ) - { - zones[i]->RecordStats( event ); - } - } - } - if ( state == PREALARM ) - Event::AddPreAlarmFrame( snap_image, *timestamp, score ); - else - event->AddFrame( snap_image, *timestamp, score ); - } - if ( event && noteSetMap.size() > 0 ) - event->updateNotes( noteSetMap ); + timestamps[i] = pre_event_buffer[pre_index].timestamp; + images[i] = pre_event_buffer[pre_index].image; + pre_index = (pre_index + 1)%pre_event_buffer_count; } - else if ( state == ALERT ) + else + for ( int i = 0; i < pre_event_images; i++ ) { - event->AddFrame( snap_image, *timestamp ); - if ( noteSetMap.size() > 0 ) - event->updateNotes( noteSetMap ); - } - else if ( state == TAPE ) - { - if ( !(image_count%(frame_skip+1)) ) - { - if ( config.bulk_frame_interval > 1 ) - { - event->AddFrame( snap_image, *timestamp, (event->Frames()AddFrame( snap_image, *timestamp ); - } - } + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; + pre_index = (pre_index + 1)%image_buffer_count; } + + event->AddFrames( pre_event_images, images, timestamps ); } + if ( alarm_frame_count ) + { + event->SavePreAlarmFrames(); + } + } } + else if ( state != PREALARM ) + { + Info( "%s: %03d - Gone into prealarm state", name, image_count ); + shared_data->state = state = PREALARM; + } + } + else if ( state == ALERT ) + { + Info( "%s: %03d - Gone back into alarm state", name, image_count ); + shared_data->state = state = ALARM; + } + last_alarm_count = image_count; } else { - if ( event ) + if ( state == ALARM ) + { + Info( "%s: %03d - Gone into alert state", name, image_count ); + shared_data->state = state = ALERT; + } + else if ( state == ALERT ) + { + if ( image_count-last_alarm_count > post_event_count ) { - Info( "%s: %03d - Closing event %d, trigger off", name, image_count, event->Id() ); + Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() ); + //if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE ) + if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) + { + shared_data->state = state = IDLE; + Info( "%s: %03d - Closing event %d, alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); closeEvent(); + } + else + { + shared_data->state = state = TAPE; + } } - shared_data->state = state = IDLE; - last_section_mod = 0; + } + if ( state == PREALARM ) + { + if ( function != MOCORD ) + { + shared_data->state = state = IDLE; + } + else + { + shared_data->state = state = TAPE; + } + } + if ( Event::PreAlarmCount() ) + Event::EmptyPreAlarmFrames(); } - if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) ) + if ( state != IDLE ) { - if ( state == ALARM ) { - ref_image.Blend( *snap_image, alarm_ref_blend_perc ); - } else { - ref_image.Blend( *snap_image, ref_blend_perc ); + if ( state == PREALARM || state == ALARM ) + { + if ( config.create_analysis_images ) + { + bool got_anal_image = false; + alarm_image.Assign( *snap_image ); + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( zones[i]->AlarmImage() ) + { + alarm_image.Overlay( *(zones[i]->AlarmImage()) ); + got_anal_image = true; + } + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( got_anal_image ) + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image ); + else + event->AddFrame( snap_image, *timestamp, score, &alarm_image ); + } + else + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } } + else + { + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } + if ( event && noteSetMap.size() > 0 ) + event->updateNotes( noteSetMap ); + } + else if ( state == ALERT ) + { + event->AddFrame( snap_image, *timestamp ); + if ( noteSetMap.size() > 0 ) + event->updateNotes( noteSetMap ); + } + else if ( state == TAPE ) + { + if ( !(image_count%(frame_skip+1)) ) + { + if ( config.bulk_frame_interval > 1 ) + { + event->AddFrame( snap_image, *timestamp, (event->Frames()AddFrame( snap_image, *timestamp ); + } + } + } } - last_signal = signal; + } } - - shared_data->last_read_index = index%image_buffer_count; - //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; - shared_data->last_read_time = now.tv_sec; - - if ( analysis_fps ) + else { - // If analysis fps is set, add analysed image to dedicated pre event buffer - int pre_index = image_count%pre_event_buffer_count; - pre_event_buffer[pre_index].image->Assign(*snap->image); - memcpy( pre_event_buffer[pre_index].timestamp, snap->timestamp, sizeof(struct timeval) ); + if ( event ) + { + Info( "%s: %03d - Closing event %d, trigger off", name, image_count, event->Id() ); + closeEvent(); + } + shared_data->state = state = IDLE; + last_section_mod = 0; } + if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) ) + { + if ( state == ALARM ) { + ref_image.Blend( *snap_image, alarm_ref_blend_perc ); + } else { + ref_image.Blend( *snap_image, ref_blend_perc ); + } + } + last_signal = signal; + } - image_count++; + shared_data->last_read_index = index%image_buffer_count; + //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; + shared_data->last_read_time = now.tv_sec; - return( true ); + if ( analysis_fps ) + { + // If analysis fps is set, add analysed image to dedicated pre event buffer + int pre_index = image_count%pre_event_buffer_count; + pre_event_buffer[pre_index].image->Assign(*snap->image); + memcpy( pre_event_buffer[pre_index].timestamp, snap->timestamp, sizeof(struct timeval) ); + } + + image_count++; + + return( true ); } void Monitor::Reload() { - Debug( 1, "Reloading monitor %s", name ); + Debug( 1, "Reloading monitor %s", name ); - if ( event ) - Info( "%s: %03d - Closing event %d, reloading", name, image_count, event->Id() ); + if ( event ) + Info( "%s: %03d - Closing event %d, reloading", name, image_count, event->Id() ); - closeEvent(); + closeEvent(); - static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id ); + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Id = '%d'", id ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - if ( n_monitors != 1 ) - { - Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); - return; - } + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors != 1 ) + { + Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); + return; + } - if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) - { - int index = 0; - function = (Function)atoi(dbrow[index++]); - enabled = atoi(dbrow[index++]); - const char *p_linked_monitors = dbrow[index++]; - strncpy( event_prefix, dbrow[index++], sizeof(event_prefix) ); - strncpy( label_format, dbrow[index++], sizeof(label_format) ); - label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; - label_size = atoi(dbrow[index++]); - warmup_count = atoi(dbrow[index++]); - pre_event_count = atoi(dbrow[index++]); - post_event_count = atoi(dbrow[index++]); - alarm_frame_count = atoi(dbrow[index++]); - section_length = atoi(dbrow[index++]); - frame_skip = atoi(dbrow[index++]); - motion_frame_skip = atoi(dbrow[index++]); - analysis_fps = dbrow[index] ? strtod(dbrow[index], NULL) : 0; index++; - analysis_update_delay = strtoul(dbrow[index++], NULL, 0); - capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; - alarm_capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; - fps_report_interval = atoi(dbrow[index++]); - ref_blend_perc = atoi(dbrow[index++]); - alarm_ref_blend_perc = atoi(dbrow[index++]); - track_motion = atoi(dbrow[index++]); - + if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + int index = 0; + function = (Function)atoi(dbrow[index++]); + enabled = atoi(dbrow[index++]); + const char *p_linked_monitors = dbrow[index++]; + strncpy( event_prefix, dbrow[index++], sizeof(event_prefix) ); + strncpy( label_format, dbrow[index++], sizeof(label_format) ); + label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; + label_size = atoi(dbrow[index++]); + warmup_count = atoi(dbrow[index++]); + pre_event_count = atoi(dbrow[index++]); + post_event_count = atoi(dbrow[index++]); + alarm_frame_count = atoi(dbrow[index++]); + section_length = atoi(dbrow[index++]); + frame_skip = atoi(dbrow[index++]); + motion_frame_skip = atoi(dbrow[index++]); + analysis_fps = dbrow[index] ? strtod(dbrow[index], NULL) : 0; index++; + analysis_update_delay = strtoul(dbrow[index++], NULL, 0); + capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + alarm_capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + fps_report_interval = atoi(dbrow[index++]); + ref_blend_perc = atoi(dbrow[index++]); + alarm_ref_blend_perc = atoi(dbrow[index++]); + track_motion = atoi(dbrow[index++]); + - if ( dbrow[index][0] == '#' ) - signal_check_colour = strtol(dbrow[index]+1,0,16); - else - signal_check_colour = strtol(dbrow[index],0,16); - index++; + if ( dbrow[index][0] == '#' ) + signal_check_colour = strtol(dbrow[index]+1,0,16); + else + signal_check_colour = strtol(dbrow[index],0,16); + index++; - shared_data->state = state = IDLE; - shared_data->alarm_x = shared_data->alarm_y = -1; - if ( enabled ) - shared_data->active = true; - ready_count = image_count+warmup_count; + shared_data->state = state = IDLE; + shared_data->alarm_x = shared_data->alarm_y = -1; + if ( enabled ) + shared_data->active = true; + ready_count = image_count+warmup_count; - ReloadLinkedMonitors( p_linked_monitors ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - mysql_free_result( result ); + ReloadLinkedMonitors( p_linked_monitors ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + mysql_free_result( result ); - ReloadZones(); + ReloadZones(); } void Monitor::ReloadZones() { - Debug( 1, "Reloading zones for monitor %s", name ); - for( int i = 0; i < n_zones; i++ ) - { - delete zones[i]; - } - delete[] zones; - zones = 0; - n_zones = Zone::Load( this, zones ); - //DumpZoneImage(); + Debug( 1, "Reloading zones for monitor %s", name ); + for( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; + zones = 0; + n_zones = Zone::Load( this, zones ); + //DumpZoneImage(); } void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) { - Debug( 1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors ); - if ( n_linked_monitors ) + Debug( 1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors ); + if ( n_linked_monitors ) + { + for( int i = 0; i < n_linked_monitors; i++ ) { - for( int i = 0; i < n_linked_monitors; i++ ) - { - delete linked_monitors[i]; - } - delete[] linked_monitors; - linked_monitors = 0; + delete linked_monitors[i]; } + delete[] linked_monitors; + linked_monitors = 0; + } - n_linked_monitors = 0; - if ( p_linked_monitors ) + n_linked_monitors = 0; + if ( p_linked_monitors ) + { + int n_link_ids = 0; + unsigned int link_ids[256]; + + char link_id_str[8]; + char *dest_ptr = link_id_str; + const char *src_ptr = p_linked_monitors; + while( 1 ) { - int n_link_ids = 0; - unsigned int link_ids[256]; - - char link_id_str[8]; - char *dest_ptr = link_id_str; - const char *src_ptr = p_linked_monitors; - while( 1 ) + dest_ptr = link_id_str; + while( *src_ptr >= '0' && *src_ptr <= '9' ) + { + if ( (dest_ptr-link_id_str) < (unsigned int)(sizeof(link_id_str)-1) ) { - dest_ptr = link_id_str; - while( *src_ptr >= '0' && *src_ptr <= '9' ) - { - if ( (dest_ptr-link_id_str) < (unsigned int)(sizeof(link_id_str)-1) ) - { - *dest_ptr++ = *src_ptr++; - } - else - { - break; - } - } - // Add the link monitor - if ( dest_ptr != link_id_str ) - { - *dest_ptr = '\0'; - unsigned int link_id = atoi(link_id_str); - if ( link_id > 0 && link_id != id) - { - Debug( 3, "Found linked monitor id %d", link_id ); - int j; - for ( j = 0; j < n_link_ids; j++ ) - { - if ( link_ids[j] == link_id ) - break; - } - if ( j == n_link_ids ) // Not already found - { - link_ids[n_link_ids++] = link_id; - } - } - } - if ( !*src_ptr ) - break; - while( *src_ptr && (*src_ptr < '0' || *src_ptr > '9') ) - src_ptr++; - if ( !*src_ptr ) - break; + *dest_ptr++ = *src_ptr++; } - if ( n_link_ids > 0 ) + else { - Debug( 1, "Linking to %d monitors", n_link_ids ); - linked_monitors = new MonitorLink *[n_link_ids]; - int count = 0; - for ( int i = 0; i < n_link_ids; i++ ) - { - Debug( 1, "Checking linked monitor %d", link_ids[i] ); - - static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - if ( n_monitors == 1 ) - { - MYSQL_ROW dbrow = mysql_fetch_row( result ); - Debug( 1, "Linking to monitor %d", link_ids[i] ); - linked_monitors[count++] = new MonitorLink( link_ids[i], dbrow[1] ); - } - else - { - Warning( "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] ); - } - mysql_free_result( result ); - } - n_linked_monitors = count; + break; } + } + // Add the link monitor + if ( dest_ptr != link_id_str ) + { + *dest_ptr = '\0'; + unsigned int link_id = atoi(link_id_str); + if ( link_id > 0 && link_id != id) + { + Debug( 3, "Found linked monitor id %d", link_id ); + int j; + for ( j = 0; j < n_link_ids; j++ ) + { + if ( link_ids[j] == link_id ) + break; + } + if ( j == n_link_ids ) // Not already found + { + link_ids[n_link_ids++] = link_id; + } + } + } + if ( !*src_ptr ) + break; + while( *src_ptr && (*src_ptr < '0' || *src_ptr > '9') ) + src_ptr++; + if ( !*src_ptr ) + break; } + if ( n_link_ids > 0 ) + { + Debug( 1, "Linking to %d monitors", n_link_ids ); + linked_monitors = new MonitorLink *[n_link_ids]; + int count = 0; + for ( int i = 0; i < n_link_ids; i++ ) + { + Debug( 1, "Checking linked monitor %d", link_ids[i] ); + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors == 1 ) + { + MYSQL_ROW dbrow = mysql_fetch_row( result ); + Debug( 1, "Linking to monitor %d", link_ids[i] ); + linked_monitors[count++] = new MonitorLink( link_ids[i], dbrow[1] ); + } + else + { + Warning( "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] ); + } + mysql_free_result( result ); + } + n_linked_monitors = count; + } + } } #if ZM_HAS_V4L int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) { - std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'"; - if ( device[0] ) { - sql += " AND Device='"; - sql += device; - sql += "'"; - } - if ( staticConfig.SERVER_ID ) { - sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); - } - Debug( 1, "Loading Local Monitors with %s", sql.c_str() ); + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Function != 'None' and Type = 'Local'"; + if ( device[0] ) { + sql += " AND Device='"; + sql += device; + sql += "'"; + } + if ( staticConfig.SERVER_ID ) { + sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); + } + Debug( 1, "Loading Local Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - if ( !result ) { - Error( "Can't load local monitors: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( !result ) { + Error( "Can't load local monitors: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int id = atoi(dbrow[col]); col++; - const char *name = dbrow[col]; col++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; - - const char *device = dbrow[col]; col++; - int channel = atoi(dbrow[col]); col++; - int format = atoi(dbrow[col]); col++; - bool v4l_multi_buffer = config.v4l_multi_buffer; - if ( dbrow[col] ) { - if (*dbrow[col] == '0' ) { - v4l_multi_buffer = false; - } else if ( *dbrow[col] == '1' ) { - v4l_multi_buffer = true; - } - } - col++; - - int v4l_captures_per_frame = 0; - if ( dbrow[col] ) { - v4l_captures_per_frame = atoi(dbrow[col]); - } else { - v4l_captures_per_frame = config.captures_per_frame; - } -Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); - col++; - const char *method = dbrow[col]; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - int palette = atoi(dbrow[col]); col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; - - const char *event_prefix = dbrow[col]; col++; - const char *label_format = dbrow[col]; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = atoi(dbrow[col]); col++; - - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - - int signal_check_colour; - if ( dbrow[col][0] == '#' ) - signal_check_colour = strtol(dbrow[col]+1,0,16); - else - signal_check_colour = strtol(dbrow[col],0,16); - col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - - int extras = (deinterlacing>>24)&0xff; - - Camera *camera = new LocalCamera( - id, - device, - channel, - format, - v4l_multi_buffer, - v4l_captures_per_frame, - method, - cam_width, - cam_height, - colours, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - extras - ); - - monitors[i] = new Monitor( - id, - name, - server_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - signal_check_colour, - embed_exif, - purpose, - 0, - 0 - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); - - return( n_monitors ); -} -#endif // ZM_HAS_V4L - -int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) -{ - std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'"; - if ( staticConfig.SERVER_ID ) { - sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); - } - - if ( protocol ) { - sql += stringtf(" AND Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); - } - - Debug( 1, "Loading Remote Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - if ( !result ) { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; - - int id = atoi(dbrow[col]); col++; - std::string name = dbrow[col]; col++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; - - std::string protocol = dbrow[col]; col++; - std::string method = dbrow[col]; col++; - std::string host = dbrow[col]; col++; - std::string port = dbrow[col]; col++; - std::string path = dbrow[col]; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - /* int palette = atoi(dbrow[col]); */ col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - bool rtsp_describe = (*dbrow[col] != '0'); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; - - std::string event_prefix = dbrow[col]; col++; - std::string label_format = dbrow[col]; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = atoi(dbrow[col]); col++; - - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - - Camera *camera = 0; - if ( protocol == "http" ) - { - camera = new RemoteCameraHttp( - id, - method, - host, // Host - port, // Port - path, // Path - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } -#if HAVE_LIBAVFORMAT - else if ( protocol == "rtsp" ) - { - camera = new RemoteCameraRtsp( - id, - method, - host, // Host - port, // Port - path, // Path - cam_width, - cam_height, - rtsp_describe, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } -#endif // HAVE_LIBAVFORMAT - else - { - Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); - } - - monitors[i] = new Monitor( - id, - name.c_str(), - server_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - event_prefix.c_str(), - label_format.c_str(), - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - RGB_WHITE, - embed_exif, - purpose, - 0, - 0 - - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); - - return( n_monitors ); -} - -int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) -{ - std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'"; - if ( file[0] ) { - sql += " AND Path='"; - sql += file; - sql += "'"; - } - if ( staticConfig.SERVER_ID ) { - sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); - } - Debug( 1, "Loading File Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; - - int id = atoi(dbrow[col]); col++; - const char *name = dbrow[col]; col++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; - - const char *path = dbrow[col]; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - /* int palette = atoi(dbrow[col]); */ col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; - - const char *event_prefix = dbrow[col]; col++; - const char *label_format = dbrow[col]; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = atoi(dbrow[col]); col++; - - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - - Camera *camera = new FileCamera( - id, - path, // File - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - - monitors[i] = new Monitor( - id, - name, - server_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - embed_exif, - RGB_WHITE, - purpose, - 0, - 0 - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); - - return( n_monitors ); -} - -#if HAVE_LIBAVFORMAT -int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) -{ - std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'"; - if ( file[0] ) { - sql += " AND Path = '"; - sql += file; - sql += "'"; - } - if ( staticConfig.SERVER_ID ) { - sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); - } - Debug( 1, "Loading FFMPEG Monitors with %s", sql.c_str() ); - MYSQL_RES *result = zmDbFetch( sql.c_str() ); - if ( ! result ) { - Error( "Cannot load FfmpegMonitors" ); - exit( mysql_errno( &dbconn ) ); - } - - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); - delete[] monitors; - monitors = new Monitor *[n_monitors]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; - - int id = atoi(dbrow[col]); col++; - const char *name = dbrow[col]; col++; - unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - int function = atoi(dbrow[col]); col++; - int enabled = atoi(dbrow[col]); col++; - const char *linked_monitors = dbrow[col]; col++; - - const char *path = dbrow[col]; col++; - const char *method = dbrow[col]; col++; - const char *options = dbrow[col]; col++; - - int width = atoi(dbrow[col]); col++; - int height = atoi(dbrow[col]); col++; - int colours = atoi(dbrow[col]); col++; - /* int palette = atoi(dbrow[col]); */ col++; - Orientation orientation = (Orientation)atoi(dbrow[col]); col++; - unsigned int deinterlacing = atoi(dbrow[col]); col++; - int brightness = atoi(dbrow[col]); col++; - int contrast = atoi(dbrow[col]); col++; - int hue = atoi(dbrow[col]); col++; - int colour = atoi(dbrow[col]); col++; - - const char *event_prefix = dbrow[col]; col++; - const char *label_format = dbrow[col]; col++; - - int label_x = atoi(dbrow[col]); col++; - int label_y = atoi(dbrow[col]); col++; - int label_size = atoi(dbrow[col]); col++; - - int image_buffer_count = atoi(dbrow[col]); col++; - int warmup_count = atoi(dbrow[col]); col++; - int pre_event_count = atoi(dbrow[col]); col++; - int post_event_count = atoi(dbrow[col]); col++; - int stream_replay_buffer = atoi(dbrow[col]); col++; - int alarm_frame_count = atoi(dbrow[col]); col++; - int section_length = atoi(dbrow[col]); col++; - int frame_skip = atoi(dbrow[col]); col++; - int motion_frame_skip = atoi(dbrow[col]); col++; - double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; - unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); - int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; - int fps_report_interval = atoi(dbrow[col]); col++; - int ref_blend_perc = atoi(dbrow[col]); col++; - int alarm_ref_blend_perc = atoi(dbrow[col]); col++; - int track_motion = atoi(dbrow[col]); col++; - bool embed_exif = (*dbrow[col] != '0'); col++; - - int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); - int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - - Camera *camera = new FfmpegCamera( - id, - path, // File - method, - options, - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - - monitors[i] = new Monitor( - id, - name, - server_id, - function, - enabled, - linked_monitors, - camera, - orientation, - deinterlacing, - event_prefix, - label_format, - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - embed_exif, - RGB_WHITE, - purpose, - 0, - 0 - ); - Zone **zones = 0; - int n_zones = Zone::Load( monitors[i], zones ); - monitors[i]->AddZones( n_zones, zones ); - monitors[i]->AddPrivacyBitmask( zones ); - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); - - return( n_monitors ); -} -#endif // HAVE_LIBAVFORMAT - -Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) -{ - std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id ); - - MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ); - if ( ! dbrow ) { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - Monitor *monitor = 0; - unsigned int col = 0; - - unsigned int id = atoi(dbrow[col]); col++; - std::string name = dbrow[col]; col++; + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; - std::string type = dbrow[col]; col++; int function = atoi(dbrow[col]); col++; int enabled = atoi(dbrow[col]); col++; - std::string linked_monitors = dbrow[col]; col++; + const char *linked_monitors = dbrow[col]; col++; - std::string device = dbrow[col]; col++; + const char *device = dbrow[col]; col++; int channel = atoi(dbrow[col]); col++; int format = atoi(dbrow[col]); col++; - bool v4l_multi_buffer = config.v4l_multi_buffer; if ( dbrow[col] ) { - if (*dbrow[col] == '0' ) { - v4l_multi_buffer = false; - } else if ( *dbrow[col] == '1' ) { - v4l_multi_buffer = true; - } + if (*dbrow[col] == '0' ) { + v4l_multi_buffer = false; + } else if ( *dbrow[col] == '1' ) { + v4l_multi_buffer = true; + } } col++; - + int v4l_captures_per_frame = 0; if ( dbrow[col] ) { - v4l_captures_per_frame = atoi(dbrow[col]); + v4l_captures_per_frame = atoi(dbrow[col]); } else { - v4l_captures_per_frame = config.captures_per_frame; + v4l_captures_per_frame = config.captures_per_frame; } Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); col++; - - std::string protocol = dbrow[col]; col++; - std::string method = dbrow[col]; col++; - std::string host = dbrow[col]; col++; - std::string port = dbrow[col]; col++; - std::string path = dbrow[col]; col++; - std::string options = dbrow[col]; col++; - std::string user = dbrow[col]; col++; - std::string pass = dbrow[col]; col++; + const char *method = dbrow[col]; col++; int width = atoi(dbrow[col]); col++; int height = atoi(dbrow[col]); col++; @@ -2753,7 +2108,169 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); int palette = atoi(dbrow[col]); col++; Orientation orientation = (Orientation)atoi(dbrow[col]); col++; unsigned int deinterlacing = atoi(dbrow[col]); col++; - bool rtsp_describe = (*dbrow[col] != '0'); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + int label_size = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int motion_frame_skip = atoi(dbrow[col]); col++; + double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; + unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int alarm_ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); + col++; + bool embed_exif = (*dbrow[col] != '0'); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + int extras = (deinterlacing>>24)&0xff; + + Camera *camera = new LocalCamera( + id, + device, + channel, + format, + v4l_multi_buffer, + v4l_captures_per_frame, + method, + cam_width, + cam_height, + colours, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + extras + ); + + monitors[i] = new Monitor( + id, + name, + server_id, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + label_size, + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + analysis_fps, + analysis_update_delay, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + signal_check_colour, + embed_exif, + purpose, + 0, + 0 + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + monitors[i]->AddPrivacyBitmask( zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} +#endif // ZM_HAS_V4L + +int Monitor::LoadRemoteMonitors( const char *protocol, const char *host, const char *port, const char *path, Monitor **&monitors, Purpose purpose ) +{ + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Remote'"; + if ( staticConfig.SERVER_ID ) { + sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); + } + + if ( protocol ) { + sql += stringtf(" AND Protocol = '%s' and Host = '%s' and Port = '%s' and Path = '%s'", protocol, host, port, path ); + } + + Debug( 1, "Loading Remote Monitors with %s", sql.c_str() ); + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( !result ) { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + bool rtsp_describe = (*dbrow[col] != '0'); col++; int brightness = atoi(dbrow[col]); col++; int contrast = atoi(dbrow[col]); col++; int hue = atoi(dbrow[col]); col++; @@ -2783,434 +2300,917 @@ Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); int ref_blend_perc = atoi(dbrow[col]); col++; int alarm_ref_blend_perc = atoi(dbrow[col]); col++; int track_motion = atoi(dbrow[col]); col++; - - int signal_check_colour; - if ( dbrow[col][0] == '#' ) - signal_check_colour = strtol(dbrow[col]+1,0,16); - else - signal_check_colour = strtol(dbrow[col],0,16); - col++; bool embed_exif = (*dbrow[col] != '0'); col++; int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); - int extras = (deinterlacing>>24)&0xff; - Camera *camera = 0; - if ( type == "Local" ) + if ( protocol == "http" ) { + camera = new RemoteCameraHttp( + id, + method, + host, // Host + port, // Port + path, // Path + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } +#if HAVE_LIBAVFORMAT + else if ( protocol == "rtsp" ) + { + camera = new RemoteCameraRtsp( + id, + method, + host, // Host + port, // Port + path, // Path + cam_width, + cam_height, + rtsp_describe, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } +#endif // HAVE_LIBAVFORMAT + else + { + Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); + } + + monitors[i] = new Monitor( + id, + name.c_str(), + server_id, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + label_size, + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + analysis_fps, + analysis_update_delay, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + RGB_WHITE, + embed_exif, + purpose, + 0, + 0 + + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + monitors[i]->AddPrivacyBitmask( zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) +{ + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'File'"; + if ( file[0] ) { + sql += " AND Path='"; + sql += file; + sql += "'"; + } + if ( staticConfig.SERVER_ID ) { + sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); + } + Debug( 1, "Loading File Monitors with %s", sql.c_str() ); + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + int label_size = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int motion_frame_skip = atoi(dbrow[col]); col++; + double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; + unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int alarm_ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + bool embed_exif = (*dbrow[col] != '0'); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = new FileCamera( + id, + path, // File + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + + monitors[i] = new Monitor( + id, + name, + server_id, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + label_size, + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + analysis_fps, + analysis_update_delay, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + embed_exif, + RGB_WHITE, + purpose, + 0, + 0 + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + monitors[i]->AddPrivacyBitmask( zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +#if HAVE_LIBAVFORMAT +int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) +{ + std::string sql = "select Id, Name, ServerId, Function+0, Enabled, LinkedMonitors, Path, Method, Options, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, Exif from Monitors where Function != 'None' and Type = 'Ffmpeg'"; + if ( file[0] ) { + sql += " AND Path = '"; + sql += file; + sql += "'"; + } + if ( staticConfig.SERVER_ID ) { + sql += stringtf( " AND ServerId=%d", staticConfig.SERVER_ID ); + } + Debug( 1, "Loading FFMPEG Monitors with %s", sql.c_str() ); + MYSQL_RES *result = zmDbFetch( sql.c_str() ); + if ( ! result ) { + Error( "Cannot load FfmpegMonitors" ); + exit( mysql_errno( &dbconn ) ); + } + + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *path = dbrow[col]; col++; + const char *method = dbrow[col]; col++; + const char *options = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + int label_size = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int motion_frame_skip = atoi(dbrow[col]); col++; + double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; + unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int alarm_ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + bool embed_exif = (*dbrow[col] != '0'); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = new FfmpegCamera( + id, + path, // File + method, + options, + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + + monitors[i] = new Monitor( + id, + name, + server_id, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + label_size, + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + analysis_fps, + analysis_update_delay, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + embed_exif, + RGB_WHITE, + purpose, + 0, + 0 + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + monitors[i]->AddPrivacyBitmask( zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} +#endif // HAVE_LIBAVFORMAT + +Monitor *Monitor::Load( unsigned int p_id, bool load_zones, Purpose purpose ) +{ + std::string sql = stringtf( "select Id, Name, ServerId, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, V4LMultiBuffer, V4LCapturesPerFrame, Protocol, Method, Host, Port, Path, Options, User, Pass, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, RTSPDescribe, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, LabelSize, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MotionFrameSkip, AnalysisFPS, AnalysisUpdateDelay, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, AlarmRefBlendPerc, TrackMotion, SignalCheckColour, Exif from Monitors where Id = %d", p_id ); + + MYSQL_ROW dbrow = zmDbFetchOne( sql.c_str() ); + if ( ! dbrow ) { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + Monitor *monitor = 0; + unsigned int col = 0; + + unsigned int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + unsigned int server_id = dbrow[col] ? atoi(dbrow[col]) : 0; col++; + std::string type = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + std::string linked_monitors = dbrow[col]; col++; + + std::string device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + + bool v4l_multi_buffer = config.v4l_multi_buffer; + if ( dbrow[col] ) { + if (*dbrow[col] == '0' ) { + v4l_multi_buffer = false; + } else if ( *dbrow[col] == '1' ) { + v4l_multi_buffer = true; + } + } + col++; + + int v4l_captures_per_frame = 0; + if ( dbrow[col] ) { + v4l_captures_per_frame = atoi(dbrow[col]); + } else { + v4l_captures_per_frame = config.captures_per_frame; + } +Debug( 1, "Got %d for v4l_captures_per_frame", v4l_captures_per_frame ); + col++; + + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + std::string options = dbrow[col]; col++; + std::string user = dbrow[col]; col++; + std::string pass = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + bool rtsp_describe = (*dbrow[col] != '0'); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + int label_size = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); col++; + int motion_frame_skip = atoi(dbrow[col]); col++; + double analysis_fps = dbrow[col] ? strtod(dbrow[col], NULL) : 0; col++; + unsigned int analysis_update_delay = strtoul(dbrow[col++], NULL, 0); + int capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int alarm_capture_delay = (dbrow[col]&&atof(dbrow[col])>0.0)?int(DT_PREC_3/atof(dbrow[col])):0; col++; + int fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int alarm_ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); + col++; + bool embed_exif = (*dbrow[col] != '0'); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + int extras = (deinterlacing>>24)&0xff; + + Camera *camera = 0; + if ( type == "Local" ) + { #if ZM_HAS_V4L - camera = new LocalCamera( - id, - device.c_str(), - channel, - format, - v4l_multi_buffer, - v4l_captures_per_frame, - method, - cam_width, - cam_height, - colours, - palette, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE, - extras - ); + camera = new LocalCamera( + id, + device.c_str(), + channel, + format, + v4l_multi_buffer, + v4l_captures_per_frame, + method, + cam_width, + cam_height, + colours, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + extras + ); #else // ZM_HAS_V4L - Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id ); + Fatal( "You must have video4linux libraries and headers installed to use local analog or USB cameras for monitor %d", id ); #endif // ZM_HAS_V4L - } - else if ( type == "Remote" ) + } + else if ( type == "Remote" ) + { + if ( protocol == "http" ) { - if ( protocol == "http" ) - { - camera = new RemoteCameraHttp( - id, - method.c_str(), - host.c_str(), - port.c_str(), - path.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } - else if ( protocol == "rtsp" ) - { -#if HAVE_LIBAVFORMAT - camera = new RemoteCameraRtsp( - id, - method.c_str(), - host.c_str(), - port.c_str(), - path.c_str(), - cam_width, - cam_height, - rtsp_describe, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); -#else // HAVE_LIBAVFORMAT - Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); -#endif // HAVE_LIBAVFORMAT - } - else - { - Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); - } + camera = new RemoteCameraHttp( + id, + method.c_str(), + host.c_str(), + port.c_str(), + path.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); } - else if ( type == "File" ) - { - camera = new FileCamera( - id, - path.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); - } - else if ( type == "Ffmpeg" ) + else if ( protocol == "rtsp" ) { #if HAVE_LIBAVFORMAT - camera = new FfmpegCamera( - id, - path.c_str(), - method, - options, - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); + camera = new RemoteCameraRtsp( + id, + method.c_str(), + host.c_str(), + port.c_str(), + path.c_str(), + cam_width, + cam_height, + rtsp_describe, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); #else // HAVE_LIBAVFORMAT - Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id ); + Fatal( "You must have ffmpeg libraries installed to use remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); #endif // HAVE_LIBAVFORMAT - } - else if (type == "Libvlc") - { -#if HAVE_LIBVLC - camera = new LibvlcCamera( - id, - path.c_str(), - method, - options, - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); -#else // HAVE_LIBVLC - Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id ); -#endif // HAVE_LIBVLC - } - else if ( type == "cURL" ) - { -#if HAVE_LIBCURL - camera = new cURLCamera( - id, - path.c_str(), - user.c_str(), - pass.c_str(), - cam_width, - cam_height, - colours, - brightness, - contrast, - hue, - colour, - purpose==CAPTURE - ); -#else // HAVE_LIBCURL - Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); -#endif // HAVE_LIBCURL } else { - Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); + Fatal( "Unexpected remote camera protocol '%s' for monitor %d", protocol.c_str(), id ); } - monitor = new Monitor( - id, - name.c_str(), - server_id, - function, - enabled, - linked_monitors.c_str(), - camera, - orientation, - deinterlacing, - event_prefix.c_str(), - label_format.c_str(), - Coord( label_x, label_y ), - label_size, - image_buffer_count, - warmup_count, - pre_event_count, - post_event_count, - stream_replay_buffer, - alarm_frame_count, - section_length, - frame_skip, - motion_frame_skip, - analysis_fps, - analysis_update_delay, - capture_delay, - alarm_capture_delay, - fps_report_interval, - ref_blend_perc, - alarm_ref_blend_perc, - track_motion, - signal_check_colour, - embed_exif, - purpose, - 0, - 0 - + } + else if ( type == "File" ) + { + camera = new FileCamera( + id, + path.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE ); + } + else if ( type == "Ffmpeg" ) + { +#if HAVE_LIBAVFORMAT + camera = new FfmpegCamera( + id, + path.c_str(), + method, + options, + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); +#else // HAVE_LIBAVFORMAT + Fatal( "You must have ffmpeg libraries installed to use ffmpeg cameras for monitor %d", id ); +#endif // HAVE_LIBAVFORMAT + } + else if (type == "Libvlc") + { +#if HAVE_LIBVLC + camera = new LibvlcCamera( + id, + path.c_str(), + method, + options, + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); +#else // HAVE_LIBVLC + Fatal( "You must have vlc libraries installed to use vlc cameras for monitor %d", id ); +#endif // HAVE_LIBVLC + } + else if ( type == "cURL" ) + { +#if HAVE_LIBCURL + camera = new cURLCamera( + id, + path.c_str(), + user.c_str(), + pass.c_str(), + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); +#else // HAVE_LIBCURL + Fatal( "You must have libcurl installed to use ffmpeg cameras for monitor %d", id ); +#endif // HAVE_LIBCURL + } + else + { + Fatal( "Bogus monitor type '%s' for monitor %d", type.c_str(), id ); + } + monitor = new Monitor( + id, + name.c_str(), + server_id, + function, + enabled, + linked_monitors.c_str(), + camera, + orientation, + deinterlacing, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + label_size, + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + motion_frame_skip, + analysis_fps, + analysis_update_delay, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + alarm_ref_blend_perc, + track_motion, + signal_check_colour, + embed_exif, + purpose, + 0, + 0 - int n_zones = 0; - if ( load_zones ) - { - Zone **zones = 0; - n_zones = Zone::Load( monitor, zones ); - monitor->AddZones( n_zones, zones ); - monitor->AddPrivacyBitmask( zones ); - } - Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); - return( monitor ); + ); + + int n_zones = 0; + if ( load_zones ) + { + Zone **zones = 0; + n_zones = Zone::Load( monitor, zones ); + monitor->AddZones( n_zones, zones ); + monitor->AddPrivacyBitmask( zones ); + } + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name.c_str(), n_zones ); + return( monitor ); } int Monitor::Capture() { - static int FirstCapture = 1; - int captureResult; + static int FirstCapture = 1; + int captureResult; - int index = image_count%image_buffer_count; - Image* capture_image = image_buffer[index].image; + int index = image_count%image_buffer_count; + Image* capture_image = image_buffer[index].image; - if ( (deinterlacing & 0xff) == 4) { - if ( FirstCapture != 1 ) { - /* Copy the next image into the shared memory */ - capture_image->CopyBuffer(*(next_buffer.image)); - } + if ( (deinterlacing & 0xff) == 4) { + if ( FirstCapture != 1 ) { + /* Copy the next image into the shared memory */ + capture_image->CopyBuffer(*(next_buffer.image)); + } - /* Capture a new next image */ - captureResult = camera->Capture(*(next_buffer.image)); + /* Capture a new next image */ + captureResult = camera->Capture(*(next_buffer.image)); - if ( FirstCapture ) { - FirstCapture = 0; - return 0; - } + if ( FirstCapture ) { + FirstCapture = 0; + return 0; + } - } else { - /* Capture directly into image buffer, avoiding the need to memcpy() */ - captureResult = camera->Capture(*capture_image); - } + } else { + /* Capture directly into image buffer, avoiding the need to memcpy() */ + captureResult = camera->Capture(*capture_image); + } + + if ( captureResult != 0 ) + { + // Unable to capture image for temporary reason + // Fake a signal loss image + Rgb signalcolor; + signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ + capture_image->Fill(signalcolor); + captureResult = 0; + } else { + captureResult = 1; + } + + if ( captureResult == 1 ) + { - if ( captureResult != 0 ) - { - // Unable to capture image for temporary reason - // Fake a signal loss image - Rgb signalcolor; - signalcolor = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ - capture_image->Fill(signalcolor); - captureResult = 0; - } else { - captureResult = 1; + /* Deinterlacing */ + if ( (deinterlacing & 0xff) == 1 ) { + capture_image->Deinterlace_Discard(); + } else if ( (deinterlacing & 0xff) == 2 ) { + capture_image->Deinterlace_Linear(); + } else if ( (deinterlacing & 0xff) == 3 ) { + capture_image->Deinterlace_Blend(); + } else if ( (deinterlacing & 0xff) == 4 ) { + capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff ); + } else if ( (deinterlacing & 0xff) == 5 ) { + capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff ); } - if ( captureResult == 1 ) + + if ( orientation != ROTATE_0 ) { - - /* Deinterlacing */ - if ( (deinterlacing & 0xff) == 1 ) { - capture_image->Deinterlace_Discard(); - } else if ( (deinterlacing & 0xff) == 2 ) { - capture_image->Deinterlace_Linear(); - } else if ( (deinterlacing & 0xff) == 3 ) { - capture_image->Deinterlace_Blend(); - } else if ( (deinterlacing & 0xff) == 4 ) { - capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff ); - } else if ( (deinterlacing & 0xff) == 5 ) { - capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff ); - } - - - if ( orientation != ROTATE_0 ) + switch ( orientation ) + { + case ROTATE_0 : { - switch ( orientation ) - { - case ROTATE_0 : - { - // No action required - break; - } - case ROTATE_90 : - case ROTATE_180 : - case ROTATE_270 : - { - capture_image->Rotate( (orientation-1)*90 ); - break; - } - case FLIP_HORI : - case FLIP_VERT : - { - capture_image->Flip( orientation==FLIP_HORI ); - break; - } - } + // No action required + break; } - + case ROTATE_90 : + case ROTATE_180 : + case ROTATE_270 : + { + capture_image->Rotate( (orientation-1)*90 ); + break; + } + case FLIP_HORI : + case FLIP_VERT : + { + capture_image->Flip( orientation==FLIP_HORI ); + break; + } + } } - if ( true ) { - if ( capture_image->Size() > camera->ImageSize() ) - { - Error( "Captured image %d does not match expected size %d check width, height and colour depth",capture_image->Size(),camera->ImageSize() ); - return( -1 ); - } + } + if ( true ) { - if ( ((unsigned int)index == shared_data->last_read_index) && (function > MONITOR) ) - { - Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count ); - time_t now = time(0); - double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec); - time_t last_read_delta = now - shared_data->last_read_time; - if ( last_read_delta > (image_buffer_count/approxFps) ) - { - Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta ) - shared_data->last_read_index = image_buffer_count; - } - } - - if ( privacy_bitmask ) - capture_image->MaskPrivacy( privacy_bitmask ); - - gettimeofday( image_buffer[index].timestamp, NULL ); - if ( config.timestamp_on_capture ) - { - TimestampImage( capture_image, image_buffer[index].timestamp ); - } - shared_data->signal = CheckSignal(capture_image); - shared_data->last_write_index = index; - shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; - - image_count++; - - if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) - { - time_t now = image_buffer[index].timestamp->tv_sec; - fps = double(fps_report_interval)/(now-last_fps_time); - //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); - //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); - Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps ); - last_fps_time = now; - } - - if ( shared_data->action & GET_SETTINGS ) - { - shared_data->brightness = camera->Brightness(); - shared_data->hue = camera->Hue(); - shared_data->colour = camera->Colour(); - shared_data->contrast = camera->Contrast(); - shared_data->action &= ~GET_SETTINGS; - } - if ( shared_data->action & SET_SETTINGS ) - { - camera->Brightness( shared_data->brightness ); - camera->Hue( shared_data->hue ); - camera->Colour( shared_data->colour ); - camera->Contrast( shared_data->contrast ); - shared_data->action &= ~SET_SETTINGS; - } - return( 0 ); + if ( capture_image->Size() > camera->ImageSize() ) + { + Error( "Captured image %d does not match expected size %d check width, height and colour depth",capture_image->Size(),camera->ImageSize() ); + return( -1 ); } - shared_data->signal = false; - return( -1 ); + + if ( ((unsigned int)index == shared_data->last_read_index) && (function > MONITOR) ) + { + Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count ); + time_t now = time(0); + double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec); + time_t last_read_delta = now - shared_data->last_read_time; + if ( last_read_delta > (image_buffer_count/approxFps) ) + { + Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta ) + shared_data->last_read_index = image_buffer_count; + } + } + + if ( privacy_bitmask ) + capture_image->MaskPrivacy( privacy_bitmask ); + + gettimeofday( image_buffer[index].timestamp, NULL ); + if ( config.timestamp_on_capture ) + { + TimestampImage( capture_image, image_buffer[index].timestamp ); + } + shared_data->signal = CheckSignal(capture_image); + shared_data->last_write_index = index; + shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; + + image_count++; + + if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + { + time_t now = image_buffer[index].timestamp->tv_sec; + fps = double(fps_report_interval)/(now-last_fps_time); + //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); + //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); + Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps ); + last_fps_time = now; + } + + if ( shared_data->action & GET_SETTINGS ) + { + shared_data->brightness = camera->Brightness(); + shared_data->hue = camera->Hue(); + shared_data->colour = camera->Colour(); + shared_data->contrast = camera->Contrast(); + shared_data->action &= ~GET_SETTINGS; + } + if ( shared_data->action & SET_SETTINGS ) + { + camera->Brightness( shared_data->brightness ); + camera->Hue( shared_data->hue ); + camera->Colour( shared_data->colour ); + camera->Contrast( shared_data->contrast ); + shared_data->action &= ~SET_SETTINGS; + } + return( 0 ); + } + shared_data->signal = false; + return( -1 ); } void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const { - if ( label_format[0] ) - { - // Expand the strftime macros first - char label_time_text[256]; - strftime( label_time_text, sizeof(label_time_text), label_format, localtime( &ts_time->tv_sec ) ); + if ( label_format[0] ) + { + // Expand the strftime macros first + char label_time_text[256]; + strftime( label_time_text, sizeof(label_time_text), label_format, localtime( &ts_time->tv_sec ) ); - char label_text[1024]; - const char *s_ptr = label_time_text; - char *d_ptr = label_text; - while ( *s_ptr && ((d_ptr-label_text) < (unsigned int)sizeof(label_text)) ) + char label_text[1024]; + const char *s_ptr = label_time_text; + char *d_ptr = label_text; + while ( *s_ptr && ((d_ptr-label_text) < (unsigned int)sizeof(label_text)) ) + { + if ( *s_ptr == '%' ) + { + bool found_macro = false; + switch ( *(s_ptr+1) ) { - if ( *s_ptr == '%' ) - { - bool found_macro = false; - switch ( *(s_ptr+1) ) - { - case 'N' : - d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", name ); - found_macro = true; - break; - case 'Q' : - d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", trigger_data->trigger_showtext ); - found_macro = true; - break; - case 'f' : - d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%02ld", ts_time->tv_usec/10000 ); - found_macro = true; - break; - } - if ( found_macro ) - { - s_ptr += 2; - continue; - } - } - *d_ptr++ = *s_ptr++; + case 'N' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", name ); + found_macro = true; + break; + case 'Q' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", trigger_data->trigger_showtext ); + found_macro = true; + break; + case 'f' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%02ld", ts_time->tv_usec/10000 ); + found_macro = true; + break; } - *d_ptr = '\0'; - ts_image->Annotate( label_text, label_coord, label_size ); + if ( found_macro ) + { + s_ptr += 2; + continue; + } + } + *d_ptr++ = *s_ptr++; } + *d_ptr = '\0'; + ts_image->Annotate( label_text, label_coord, label_size ); + } } bool Monitor::closeEvent() { - if ( event ) + if ( event ) + { + if ( function == RECORD || function == MOCORD ) { - if ( function == RECORD || function == MOCORD ) - { - gettimeofday( &(event->EndTime()), NULL ); - } - delete event; - event = 0; - return( true ); + gettimeofday( &(event->EndTime()), NULL ); } - return( false ); + delete event; + event = 0; + return( true ); + } + return( false ); } //----------------------------------------- @@ -3246,151 +3246,151 @@ bool Monitor::closeEvent() /* bool Monitor::OurCheckAlarms( Zone *zone, const Image *pImage ) { - Info("Entering OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); - unsigned char black_thr = 23; - int min_alarm_score = 10; - int max_alarm_score = 99; - //bool alarm = false; - unsigned int score; - Polygon zone_polygon = zone->GetPolygon(); - Info("Got polygon of a zone. It has %d vertices.", zone_polygon.getNumCoords()); + Info("Entering OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + unsigned char black_thr = 23; + int min_alarm_score = 10; + int max_alarm_score = 99; + //bool alarm = false; + unsigned int score; + Polygon zone_polygon = zone->GetPolygon(); + Info("Got polygon of a zone. It has %d vertices.", zone_polygon.getNumCoords()); zone->ResetStats(); - Info("ResetStats done."); + Info("ResetStats done."); - if ( !zone->CheckOverloadCount() ) - { - Info("CheckOverloadCount() return false, we'll return false."); - return( false ); - } + if ( !zone->CheckOverloadCount() ) + { + Info("CheckOverloadCount() return false, we'll return false."); + return( false ); + } - Image *pMaskImage = new Image(pImage->Width(), pImage->Height(), ZM_COLOUR_GRAY8, pImage->SubpixelOrder()); - Info("Mask image created."); + Image *pMaskImage = new Image(pImage->Width(), pImage->Height(), ZM_COLOUR_GRAY8, pImage->SubpixelOrder()); + Info("Mask image created."); - pMaskImage->Fill(BLACK); - Info("Mask image filled with BLACK."); - if (pImage->Colours() == ZM_COLOUR_GRAY8) + pMaskImage->Fill(BLACK); + Info("Mask image filled with BLACK."); + if (pImage->Colours() == ZM_COLOUR_GRAY8) + { + Info("Analysed image is not colored! Set score = 0."); + score = 0; + } + else + { + Info("Start processing image."); + //Process image + unsigned char *buffer = (unsigned char*)pImage->Buffer(); + unsigned char *mask_buffer = (unsigned char*)pMaskImage->Buffer(); + + int black_pixels_count = 0; + Info("Loop for black pixels counting and mask filling."); + while (buffer < (pImage->Buffer() + pImage->Size())) { - Info("Analysed image is not colored! Set score = 0."); - score = 0; - } - else - { - Info("Start processing image."); - //Process image - unsigned char *buffer = (unsigned char*)pImage->Buffer(); - unsigned char *mask_buffer = (unsigned char*)pMaskImage->Buffer(); - - int black_pixels_count = 0; - Info("Loop for black pixels counting and mask filling."); - while (buffer < (pImage->Buffer() + pImage->Size())) - { - if ( (RED(buffer) < black_thr) && (GREEN(buffer) < black_thr) && (BLUE(buffer) < black_thr) ) - { - *mask_buffer = WHITE; - black_pixels_count++; - } - buffer += pImage->Colours(); - mask_buffer++; - } - - if ( !black_pixels_count ) - { - delete pMaskImage; - return( false ); - } - score = (100*black_pixels_count)/zone_polygon.Area(); - Info("Number of black pixels is %d, zone polygon area is %d, score is %d", black_pixels_count, zone_polygon.Area(), score); - - if ( min_alarm_score && ( score < min_alarm_score) ) - { - delete pMaskImage; - return( false ); - } - if ( max_alarm_score && (score > max_alarm_score) ) - { - zone->SetOverloadCount(zone->GetOverloadFrames()); - delete pMaskImage; - return( false ); - } + if ( (RED(buffer) < black_thr) && (GREEN(buffer) < black_thr) && (BLUE(buffer) < black_thr) ) + { + *mask_buffer = WHITE; + black_pixels_count++; + } + buffer += pImage->Colours(); + mask_buffer++; } - zone->SetScore(score); - Info("Score have been set in zone."); - //Get mask - Rgb alarm_colour = RGB_RED; + if ( !black_pixels_count ) + { + delete pMaskImage; + return( false ); + } + score = (100*black_pixels_count)/zone_polygon.Area(); + Info("Number of black pixels is %d, zone polygon area is %d, score is %d", black_pixels_count, zone_polygon.Area(), score); + + if ( min_alarm_score && ( score < min_alarm_score) ) + { + delete pMaskImage; + return( false ); + } + if ( max_alarm_score && (score > max_alarm_score) ) + { + zone->SetOverloadCount(zone->GetOverloadFrames()); + delete pMaskImage; + return( false ); + } + } + + zone->SetScore(score); + Info("Score have been set in zone."); + //Get mask + Rgb alarm_colour = RGB_RED; Image *tempImage = pMaskImage->HighlightEdges(alarm_colour, &zone_polygon.Extent() ); - Info("After HighlightEdges"); + Info("After HighlightEdges"); - zone->SetAlarmImage(tempImage); - Info("After SetAlarmImage"); - delete pMaskImage; - Info("After Delete pMaskImage"); - delete tempImage; + zone->SetAlarmImage(tempImage); + Info("After SetAlarmImage"); + delete pMaskImage; + Info("After Delete pMaskImage"); + delete tempImage; - Info("Leaving OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); - return true; + Info("Leaving OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + return true; } unsigned int Monitor::DetectBlack(const Image &comp_image, Event::StringSet &zoneSet ) { - Info("Entering DetectBlack >>>>>>>>>>>>>>>>>>>>>>>>>>"); - bool alarm = false; - unsigned int score = 0; + Info("Entering DetectBlack >>>>>>>>>>>>>>>>>>>>>>>>>>"); + bool alarm = false; + unsigned int score = 0; - if ( n_zones <= 0 ) return( alarm ); + if ( n_zones <= 0 ) return( alarm ); -// Coord alarm_centre; -// int top_score = -1; +// Coord alarm_centre; +// int top_score = -1; - // Find all alarm pixels in active zones - Info("Number of zones to process %d", n_zones); - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + // Find all alarm pixels in active zones + Info("Number of zones to process %d", n_zones); + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsActive() ) { - Zone *zone = zones[n_zone]; - if ( !zone->IsActive() ) - { - continue; - } - Debug( 3, "Checking active zone %s", zone->Label() ); - Info( "Checking active zone %s", zone->Label() ); - if ( OurCheckAlarms( zone, &comp_image ) ) - { - Info("OurCheckAlarm is TRUE!!!!!!"); - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); - Info( "Zone is alarmed, zone score = %d", zone->Score() ); - zoneSet.insert( zone->Label() ); -// if ( config.opt_control && track_motion ) -// { -// if ( (int)zone->Score() > top_score ) -// { -// top_score = zone->Score(); -// alarm_centre = zone->GetAlarmCentre(); -// } -// } - } - Info( "Finish checking active zone %s", zone->Label() ); + continue; } + Debug( 3, "Checking active zone %s", zone->Label() ); + Info( "Checking active zone %s", zone->Label() ); + if ( OurCheckAlarms( zone, &comp_image ) ) + { + Info("OurCheckAlarm is TRUE!!!!!!"); + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + Info( "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); +// if ( config.opt_control && track_motion ) +// { +// if ( (int)zone->Score() > top_score ) +// { +// top_score = zone->Score(); +// alarm_centre = zone->GetAlarmCentre(); +// } +// } + } + Info( "Finish checking active zone %s", zone->Label() ); + } -// if ( top_score > 0 ) -// { -// shared_data->alarm_x = alarm_centre.X(); -// shared_data->alarm_y = alarm_centre.Y(); +// if ( top_score > 0 ) +// { +// shared_data->alarm_x = alarm_centre.X(); +// shared_data->alarm_y = alarm_centre.Y(); // -// Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); -// } -// else -// { -// shared_data->alarm_x = shared_data->alarm_y = -1; -// } +// Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); +// } +// else +// { +// shared_data->alarm_x = shared_data->alarm_y = -1; +// } - // This is a small and innocent hack to prevent scores of 0 being returned in alarm state - Info("Leaving DetectBlack <<<<<<<<<<<<<<<<<<<<<<<<<<<"); - return( score?score:alarm ); + // This is a small and innocent hack to prevent scores of 0 being returned in alarm state + Info("Leaving DetectBlack <<<<<<<<<<<<<<<<<<<<<<<<<<<"); + return( score?score:alarm ); } */ @@ -3400,1127 +3400,1127 @@ unsigned int Monitor::DetectBlack(const Image &comp_image, Event::StringSet &zon unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) { - bool alarm = false; - unsigned int score = 0; + bool alarm = false; + unsigned int score = 0; - if ( n_zones <= 0 ) return( alarm ); + if ( n_zones <= 0 ) return( alarm ); - if ( config.record_diag_images ) + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); - } - ref_image.WriteJpeg( diag_path ); + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); } + ref_image.WriteJpeg( diag_path ); + } - ref_image.Delta( comp_image, &delta_image); + ref_image.Delta( comp_image, &delta_image); - if ( config.record_diag_images ) + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); - } - delta_image.WriteJpeg( diag_path ); + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); } + delta_image.WriteJpeg( diag_path ); + } - // Blank out all exclusion zones - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + // Blank out all exclusion zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + // need previous alarmed state for preclusive zone, so don't clear just yet + if (!zone->IsPreclusive()) + zone->ClearAlarm(); + if ( !zone->IsInactive() ) { - Zone *zone = zones[n_zone]; - // need previous alarmed state for preclusive zone, so don't clear just yet - if (!zone->IsPreclusive()) - zone->ClearAlarm(); - if ( !zone->IsInactive() ) - { - continue; - } - Debug( 3, "Blanking inactive zone %s", zone->Label() ); - delta_image.Fill( RGB_BLACK, zone->GetPolygon() ); + continue; } + Debug( 3, "Blanking inactive zone %s", zone->Label() ); + delta_image.Fill( RGB_BLACK, zone->GetPolygon() ); + } - // Check preclusive zones first - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + // Check preclusive zones first + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsPreclusive() ) { - Zone *zone = zones[n_zone]; - if ( !zone->IsPreclusive() ) - { - continue; + continue; + } + int old_zone_score = zone->Score(); + bool old_zone_alarmed = zone->Alarmed(); + Debug( 3, "Checking preclusive zone %s - old score: %d, state: %s", zone->Label(),old_zone_score, zone->Alarmed()?"alarmed":"quiet" ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + //zone->ResetStats(); + } else { + // check if end of alarm + if (old_zone_alarmed) { + Debug(3, "Preclusive Zone %s alarm Ends. Prevíous score: %d", zone->Label(), old_zone_score); + if (old_zone_score > 0) { + zone->SetExtendAlarmCount(zone->GetExtendAlarmFrames()); } - int old_zone_score = zone->Score(); - bool old_zone_alarmed = zone->Alarmed(); - Debug( 3, "Checking preclusive zone %s - old score: %d, state: %s", zone->Label(),old_zone_score, zone->Alarmed()?"alarmed":"quiet" ); - if ( zone->CheckAlarms( &delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); - zoneSet.insert( zone->Label() ); - //zone->ResetStats(); + if (zone->CheckExtendAlarmCount()) { + alarm=true; + zone->SetAlarm(); } else { - // check if end of alarm - if (old_zone_alarmed) { - Debug(3, "Preclusive Zone %s alarm Ends. Prevíous score: %d", zone->Label(), old_zone_score); - if (old_zone_score > 0) { - zone->SetExtendAlarmCount(zone->GetExtendAlarmFrames()); - } - if (zone->CheckExtendAlarmCount()) { - alarm=true; - zone->SetAlarm(); - } else { - zone->ClearAlarm(); - } - } + zone->ClearAlarm(); } + } } + } - Coord alarm_centre; - int top_score = -1; + Coord alarm_centre; + int top_score = -1; + + if ( alarm ) + { + alarm = false; + score = 0; + } + else + { + // Find all alarm pixels in active zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsActive() || zone->IsPreclusive()) + { + continue; + } + Debug( 3, "Checking active zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + if ( config.opt_control && track_motion ) + { + if ( (int)zone->Score() > top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } if ( alarm ) { - alarm = false; - score = 0; + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsInclusive() ) + { + continue; + } + Debug( 3, "Checking inclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + if ( config.opt_control && track_motion ) + { + if ( zone->Score() > (unsigned int)top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } } else { - // Find all alarm pixels in active zones - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + // Find all alarm pixels in exclusive zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsExclusive() ) { - Zone *zone = zones[n_zone]; - if ( !zone->IsActive() || zone->IsPreclusive()) - { - continue; - } - Debug( 3, "Checking active zone %s", zone->Label() ); - if ( zone->CheckAlarms( &delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); - zoneSet.insert( zone->Label() ); - if ( config.opt_control && track_motion ) - { - if ( (int)zone->Score() > top_score ) - { - top_score = zone->Score(); - alarm_centre = zone->GetAlarmCentre(); - } - } - } + continue; } - - if ( alarm ) + Debug( 3, "Checking exclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) { - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - if ( !zone->IsInclusive() ) - { - continue; - } - Debug( 3, "Checking inclusive zone %s", zone->Label() ); - if ( zone->CheckAlarms( &delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); - zoneSet.insert( zone->Label() ); - if ( config.opt_control && track_motion ) - { - if ( zone->Score() > (unsigned int)top_score ) - { - top_score = zone->Score(); - alarm_centre = zone->GetAlarmCentre(); - } - } - } - } - } - else - { - // Find all alarm pixels in exclusive zones - for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) - { - Zone *zone = zones[n_zone]; - if ( !zone->IsExclusive() ) - { - continue; - } - Debug( 3, "Checking exclusive zone %s", zone->Label() ); - if ( zone->CheckAlarms( &delta_image ) ) - { - alarm = true; - score += zone->Score(); - zone->SetAlarm(); - Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); - zoneSet.insert( zone->Label() ); - } - } + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); } + } } + } - if ( top_score > 0 ) - { - shared_data->alarm_x = alarm_centre.X(); - shared_data->alarm_y = alarm_centre.Y(); + if ( top_score > 0 ) + { + shared_data->alarm_x = alarm_centre.X(); + shared_data->alarm_y = alarm_centre.Y(); - Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); - } - else - { - shared_data->alarm_x = shared_data->alarm_y = -1; - } + Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); + } + else + { + shared_data->alarm_x = shared_data->alarm_y = -1; + } - // This is a small and innocent hack to prevent scores of 0 being returned in alarm state - return( score?score:alarm ); + // This is a small and innocent hack to prevent scores of 0 being returned in alarm state + return( score?score:alarm ); } bool Monitor::DumpSettings( char *output, bool verbose ) { - output[0] = 0; + output[0] = 0; - sprintf( output+strlen(output), "Id : %d\n", id ); - sprintf( output+strlen(output), "Name : %s\n", name ); - sprintf( output+strlen(output), "Type : %s\n", camera->IsLocal()?"Local":(camera->IsRemote()?"Remote":"File") ); + sprintf( output+strlen(output), "Id : %d\n", id ); + sprintf( output+strlen(output), "Name : %s\n", name ); + sprintf( output+strlen(output), "Type : %s\n", camera->IsLocal()?"Local":(camera->IsRemote()?"Remote":"File") ); #if ZM_HAS_V4L - if ( camera->IsLocal() ) - { - sprintf( output+strlen(output), "Device : %s\n", ((LocalCamera *)camera)->Device().c_str() ); - sprintf( output+strlen(output), "Channel : %d\n", ((LocalCamera *)camera)->Channel() ); - sprintf( output+strlen(output), "Standard : %d\n", ((LocalCamera *)camera)->Standard() ); - } - else + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Device : %s\n", ((LocalCamera *)camera)->Device().c_str() ); + sprintf( output+strlen(output), "Channel : %d\n", ((LocalCamera *)camera)->Channel() ); + sprintf( output+strlen(output), "Standard : %d\n", ((LocalCamera *)camera)->Standard() ); + } + else #endif // ZM_HAS_V4L - if ( camera->IsRemote() ) - { - sprintf( output+strlen(output), "Protocol : %s\n", ((RemoteCamera *)camera)->Protocol().c_str() ); - sprintf( output+strlen(output), "Host : %s\n", ((RemoteCamera *)camera)->Host().c_str() ); - sprintf( output+strlen(output), "Port : %s\n", ((RemoteCamera *)camera)->Port().c_str() ); - sprintf( output+strlen(output), "Path : %s\n", ((RemoteCamera *)camera)->Path().c_str() ); - } - else if ( camera->IsFile() ) - { - sprintf( output+strlen(output), "Path : %s\n", ((FileCamera *)camera)->Path() ); - } + if ( camera->IsRemote() ) + { + sprintf( output+strlen(output), "Protocol : %s\n", ((RemoteCamera *)camera)->Protocol().c_str() ); + sprintf( output+strlen(output), "Host : %s\n", ((RemoteCamera *)camera)->Host().c_str() ); + sprintf( output+strlen(output), "Port : %s\n", ((RemoteCamera *)camera)->Port().c_str() ); + sprintf( output+strlen(output), "Path : %s\n", ((RemoteCamera *)camera)->Path().c_str() ); + } + else if ( camera->IsFile() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FileCamera *)camera)->Path() ); + } #if HAVE_LIBAVFORMAT - else if ( camera->IsFfmpeg() ) - { - sprintf( output+strlen(output), "Path : %s\n", ((FfmpegCamera *)camera)->Path().c_str() ); - } + else if ( camera->IsFfmpeg() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FfmpegCamera *)camera)->Path().c_str() ); + } #endif // HAVE_LIBAVFORMAT - sprintf( output+strlen(output), "Width : %d\n", camera->Width() ); - sprintf( output+strlen(output), "Height : %d\n", camera->Height() ); + sprintf( output+strlen(output), "Width : %d\n", camera->Width() ); + sprintf( output+strlen(output), "Height : %d\n", camera->Height() ); #if ZM_HAS_V4L - if ( camera->IsLocal() ) - { - sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); - } + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); + } #endif // ZM_HAS_V4L - sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); - sprintf( output+strlen(output), "Subpixel Order : %d\n", camera->SubpixelOrder() ); - sprintf( output+strlen(output), "Event Prefix : %s\n", event_prefix ); - sprintf( output+strlen(output), "Label Format : %s\n", label_format ); - sprintf( output+strlen(output), "Label Coord : %d,%d\n", label_coord.X(), label_coord.Y() ); - sprintf( output+strlen(output), "Label Size : %d\n", label_size ); - sprintf( output+strlen(output), "Image Buffer Count : %d\n", image_buffer_count ); - sprintf( output+strlen(output), "Warmup Count : %d\n", warmup_count ); - sprintf( output+strlen(output), "Pre Event Count : %d\n", pre_event_count ); - sprintf( output+strlen(output), "Post Event Count : %d\n", post_event_count ); - sprintf( output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer ); - sprintf( output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); - sprintf( output+strlen(output), "Section Length : %d\n", section_length ); - sprintf( output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?DT_PREC_3/capture_delay:0.0 ); - sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?DT_PREC_3/alarm_capture_delay:0.0 ); - sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); - sprintf( output+strlen(output), "Alarm Reference Blend %%ge : %d\n", alarm_ref_blend_perc ); - sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); - sprintf( output+strlen(output), "Function: %d - %s\n", function, - function==NONE?"None":( - function==MONITOR?"Monitor Only":( - function==MODECT?"Motion Detection":( - function==RECORD?"Continuous Record":( - function==MOCORD?"Continuous Record with Motion Detection":( - function==NODECT?"Externally Triggered only, no Motion Detection":"Unknown" - )))))); - sprintf( output+strlen(output), "Zones : %d\n", n_zones ); - for ( int i = 0; i < n_zones; i++ ) - { - zones[i]->DumpSettings( output+strlen(output), verbose ); - } - return( true ); + sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); + sprintf( output+strlen(output), "Subpixel Order : %d\n", camera->SubpixelOrder() ); + sprintf( output+strlen(output), "Event Prefix : %s\n", event_prefix ); + sprintf( output+strlen(output), "Label Format : %s\n", label_format ); + sprintf( output+strlen(output), "Label Coord : %d,%d\n", label_coord.X(), label_coord.Y() ); + sprintf( output+strlen(output), "Label Size : %d\n", label_size ); + sprintf( output+strlen(output), "Image Buffer Count : %d\n", image_buffer_count ); + sprintf( output+strlen(output), "Warmup Count : %d\n", warmup_count ); + sprintf( output+strlen(output), "Pre Event Count : %d\n", pre_event_count ); + sprintf( output+strlen(output), "Post Event Count : %d\n", post_event_count ); + sprintf( output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer ); + sprintf( output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); + sprintf( output+strlen(output), "Section Length : %d\n", section_length ); + sprintf( output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?DT_PREC_3/capture_delay:0.0 ); + sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?DT_PREC_3/alarm_capture_delay:0.0 ); + sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); + sprintf( output+strlen(output), "Alarm Reference Blend %%ge : %d\n", alarm_ref_blend_perc ); + sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); + sprintf( output+strlen(output), "Function: %d - %s\n", function, + function==NONE?"None":( + function==MONITOR?"Monitor Only":( + function==MODECT?"Motion Detection":( + function==RECORD?"Continuous Record":( + function==MOCORD?"Continuous Record with Motion Detection":( + function==NODECT?"Externally Triggered only, no Motion Detection":"Unknown" + )))))); + sprintf( output+strlen(output), "Zones : %d\n", n_zones ); + for ( int i = 0; i < n_zones; i++ ) + { + zones[i]->DumpSettings( output+strlen(output), verbose ); + } + return( true ); } bool MonitorStream::checkSwapPath( const char *path, bool create_path ) { - uid_t uid = getuid(); - gid_t gid = getgid(); + uid_t uid = getuid(); + gid_t gid = getgid(); - struct stat stat_buf; - if ( stat( path, &stat_buf ) < 0 ) + struct stat stat_buf; + if ( stat( path, &stat_buf ) < 0 ) + { + if ( create_path && errno == ENOENT ) { - if ( create_path && errno == ENOENT ) - { - Debug( 3, "Swap path '%s' missing, creating", path ); - if ( mkdir( path, 0755 ) ) - { - Error( "Can't mkdir %s: %s", path, strerror(errno)); - return( false ); - } - if ( stat( path, &stat_buf ) < 0 ) - { - Error( "Can't stat '%s': %s", path, strerror(errno) ); - return( false ); - } - } - else - { - Error( "Can't stat '%s': %s", path, strerror(errno) ); - return( false ); - } - } - if ( !S_ISDIR(stat_buf.st_mode) ) - { - Error( "Swap image path '%s' is not a directory", path ); + Debug( 3, "Swap path '%s' missing, creating", path ); + if ( mkdir( path, 0755 ) ) + { + Error( "Can't mkdir %s: %s", path, strerror(errno)); return( false ); - } - - mode_t mask = 0; - if ( uid == stat_buf.st_uid ) - { - // If we are the owner - mask = 00700; - } - else if ( gid == stat_buf.st_gid ) - { - // If we are in the owner group - mask = 00070; + } + if ( stat( path, &stat_buf ) < 0 ) + { + Error( "Can't stat '%s': %s", path, strerror(errno) ); + return( false ); + } } else { - // We are neither the owner nor in the group - mask = 00007; + Error( "Can't stat '%s': %s", path, strerror(errno) ); + return( false ); } + } + if ( !S_ISDIR(stat_buf.st_mode) ) + { + Error( "Swap image path '%s' is not a directory", path ); + return( false ); + } - if ( (stat_buf.st_mode & mask) != mask ) - { - Error( "Insufficient permissions on swap image path '%s'", path ); - return( false ); - } - return( true ); + mode_t mask = 0; + if ( uid == stat_buf.st_uid ) + { + // If we are the owner + mask = 00700; + } + else if ( gid == stat_buf.st_gid ) + { + // If we are in the owner group + mask = 00070; + } + else + { + // We are neither the owner nor in the group + mask = 00007; + } + + if ( (stat_buf.st_mode & mask) != mask ) + { + Error( "Insufficient permissions on swap image path '%s'", path ); + return( false ); + } + return( true ); } void MonitorStream::processCommand( const CmdMsg *msg ) { - Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ); - // Check for incoming command - switch( (MsgCommand)msg->msg_data[0] ) + Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ); + // Check for incoming command + switch( (MsgCommand)msg->msg_data[0] ) + { + case CMD_PAUSE : { - case CMD_PAUSE : - { - Debug( 1, "Got PAUSE command" ); + Debug( 1, "Got PAUSE command" ); - // Set paused flag - paused = true; - // Set delayed flag - delayed = true; - last_frame_sent = TV_2_FLOAT( now ); - break; - } - case CMD_PLAY : - { - Debug( 1, "Got PLAY command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - // Set delayed_play flag - delayed = true; - } - replay_rate = ZM_RATE_BASE; - break; - } - case CMD_VARPLAY : - { - Debug( 1, "Got VARPLAY command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - // Set delayed_play flag - delayed = true; - } - replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; - break; - } - case CMD_STOP : - { - Debug( 1, "Got STOP command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + last_frame_sent = TV_2_FLOAT( now ); + break; + } + case CMD_PLAY : + { + Debug( 1, "Got PLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + replay_rate = ZM_RATE_BASE; + break; + } + case CMD_VARPLAY : + { + Debug( 1, "Got VARPLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; + break; + } + case CMD_STOP : + { + Debug( 1, "Got STOP command" ); - // Clear paused flag - paused = false; - // Clear delayed_play flag - delayed = false; - break; - } - case CMD_FASTFWD : - { - Debug( 1, "Got FAST FWD command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - // Set delayed_play flag - delayed = true; - } - // Set play rate - switch ( replay_rate ) - { - case 2 * ZM_RATE_BASE : - replay_rate = 5 * ZM_RATE_BASE; - break; - case 5 * ZM_RATE_BASE : - replay_rate = 10 * ZM_RATE_BASE; - break; - case 10 * ZM_RATE_BASE : - replay_rate = 25 * ZM_RATE_BASE; - break; - case 25 * ZM_RATE_BASE : - case 50 * ZM_RATE_BASE : - replay_rate = 50 * ZM_RATE_BASE; - break; - default : - replay_rate = 2 * ZM_RATE_BASE; - break; - } - break; - } - case CMD_SLOWFWD : - { - Debug( 1, "Got SLOW FWD command" ); - // Set paused flag - paused = true; - // Set delayed flag - delayed = true; - // Set play rate - replay_rate = ZM_RATE_BASE; - // Set step - step = 1; - break; - } - case CMD_SLOWREV : - { - Debug( 1, "Got SLOW REV command" ); - // Set paused flag - paused = true; - // Set delayed flag - delayed = true; - // Set play rate - replay_rate = ZM_RATE_BASE; - // Set step - step = -1; - break; - } - case CMD_FASTREV : - { - Debug( 1, "Got FAST REV command" ); - if ( paused ) - { - // Clear paused flag - paused = false; - // Set delayed_play flag - delayed = true; - } - // Set play rate - switch ( replay_rate ) - { - case -2 * ZM_RATE_BASE : - replay_rate = -5 * ZM_RATE_BASE; - break; - case -5 * ZM_RATE_BASE : - replay_rate = -10 * ZM_RATE_BASE; - break; - case -10 * ZM_RATE_BASE : - replay_rate = -25 * ZM_RATE_BASE; - break; - case -25 * ZM_RATE_BASE : - case -50 * ZM_RATE_BASE : - replay_rate = -50 * ZM_RATE_BASE; - break; - default : - replay_rate = -2 * ZM_RATE_BASE; - break; - } - break; - } - case CMD_ZOOMIN : - { - x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; - y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; - Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); - switch ( zoom ) - { - case 100: - zoom = 150; - break; - case 150: - zoom = 200; - break; - case 200: - zoom = 300; - break; - case 300: - zoom = 400; - break; - case 400: - default : - zoom = 500; - break; - } - break; - } - case CMD_ZOOMOUT : - { - Debug( 1, "Got ZOOM OUT command" ); - switch ( zoom ) - { - case 500: - zoom = 400; - break; - case 400: - zoom = 300; - break; - case 300: - zoom = 200; - break; - case 200: - zoom = 150; - break; - case 150: - default : - zoom = 100; - break; - } - break; - } - case CMD_PAN : - { - x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; - y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; - Debug( 1, "Got PAN command, to %d,%d", x, y ); - break; - } - case CMD_SCALE : - { - scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; - Debug( 1, "Got SCALE command, to %d", scale ); - break; - } - case CMD_QUIT : - { - Info ("User initiated exit - CMD_QUIT"); - break; - } - case CMD_QUERY : - { - Debug( 1, "Got QUERY command, sending STATUS" ); - break; - } + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + break; + } + case CMD_FASTFWD : + { + Debug( 1, "Got FAST FWD command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + // Set play rate + switch ( replay_rate ) + { + case 2 * ZM_RATE_BASE : + replay_rate = 5 * ZM_RATE_BASE; + break; + case 5 * ZM_RATE_BASE : + replay_rate = 10 * ZM_RATE_BASE; + break; + case 10 * ZM_RATE_BASE : + replay_rate = 25 * ZM_RATE_BASE; + break; + case 25 * ZM_RATE_BASE : + case 50 * ZM_RATE_BASE : + replay_rate = 50 * ZM_RATE_BASE; + break; default : - { - Error( "Got unexpected command %d", msg->msg_data[0] ); - break; - } + replay_rate = 2 * ZM_RATE_BASE; + break; + } + break; } - - struct { - int id; - int state; - double fps; - int buffer_level; - int rate; - double delay; - int zoom; - bool delayed; - bool paused; - bool enabled; - bool forced; - } status_data; - - status_data.id = monitor->Id(); - status_data.fps = monitor->GetFPS(); - status_data.state = monitor->shared_data->state; - if ( playback_buffer > 0 ) - status_data.buffer_level = (MOD_ADD( (temp_write_index-temp_read_index), 0, temp_image_buffer_count )*100)/temp_image_buffer_count; - else - status_data.buffer_level = 0; - status_data.delayed = delayed; - status_data.paused = paused; - status_data.rate = replay_rate; - status_data.delay = TV_2_FLOAT( now ) - TV_2_FLOAT( last_frame_timestamp ); - status_data.zoom = zoom; - //status_data.enabled = monitor->shared_data->active; - status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF; - status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON; - Debug( 2, "L:%d, D:%d, P:%d, R:%d, d:%.3f, Z:%d, E:%d F:%d", - status_data.buffer_level, - status_data.delayed, - status_data.paused, - status_data.rate, - status_data.delay, - status_data.zoom, - status_data.enabled, - status_data.forced - ); - - DataMsg status_msg; - status_msg.msg_type = MSG_DATA_WATCH; - memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) ); - int nbytes = 0; - if ( (nbytes = sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) )) < 0 ) + case CMD_SLOWFWD : { - //if ( errno != EAGAIN ) - { - Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); - //exit( -1 ); - } + Debug( 1, "Got SLOW FWD command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = 1; + break; } + case CMD_SLOWREV : + { + Debug( 1, "Got SLOW REV command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = -1; + break; + } + case CMD_FASTREV : + { + Debug( 1, "Got FAST REV command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + // Set play rate + switch ( replay_rate ) + { + case -2 * ZM_RATE_BASE : + replay_rate = -5 * ZM_RATE_BASE; + break; + case -5 * ZM_RATE_BASE : + replay_rate = -10 * ZM_RATE_BASE; + break; + case -10 * ZM_RATE_BASE : + replay_rate = -25 * ZM_RATE_BASE; + break; + case -25 * ZM_RATE_BASE : + case -50 * ZM_RATE_BASE : + replay_rate = -50 * ZM_RATE_BASE; + break; + default : + replay_rate = -2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_ZOOMIN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); + switch ( zoom ) + { + case 100: + zoom = 150; + break; + case 150: + zoom = 200; + break; + case 200: + zoom = 300; + break; + case 300: + zoom = 400; + break; + case 400: + default : + zoom = 500; + break; + } + break; + } + case CMD_ZOOMOUT : + { + Debug( 1, "Got ZOOM OUT command" ); + switch ( zoom ) + { + case 500: + zoom = 400; + break; + case 400: + zoom = 300; + break; + case 300: + zoom = 200; + break; + case 200: + zoom = 150; + break; + case 150: + default : + zoom = 100; + break; + } + break; + } + case CMD_PAN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got PAN command, to %d,%d", x, y ); + break; + } + case CMD_SCALE : + { + scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + Debug( 1, "Got SCALE command, to %d", scale ); + break; + } + case CMD_QUIT : + { + Info ("User initiated exit - CMD_QUIT"); + break; + } + case CMD_QUERY : + { + Debug( 1, "Got QUERY command, sending STATUS" ); + break; + } + default : + { + Error( "Got unexpected command %d", msg->msg_data[0] ); + break; + } + } - // quit after sending a status, if this was a quit request - if ((MsgCommand)msg->msg_data[0]==CMD_QUIT) - exit(0); + struct { + int id; + int state; + double fps; + int buffer_level; + int rate; + double delay; + int zoom; + bool delayed; + bool paused; + bool enabled; + bool forced; + } status_data; - updateFrameRate( monitor->GetFPS() ); + status_data.id = monitor->Id(); + status_data.fps = monitor->GetFPS(); + status_data.state = monitor->shared_data->state; + if ( playback_buffer > 0 ) + status_data.buffer_level = (MOD_ADD( (temp_write_index-temp_read_index), 0, temp_image_buffer_count )*100)/temp_image_buffer_count; + else + status_data.buffer_level = 0; + status_data.delayed = delayed; + status_data.paused = paused; + status_data.rate = replay_rate; + status_data.delay = TV_2_FLOAT( now ) - TV_2_FLOAT( last_frame_timestamp ); + status_data.zoom = zoom; + //status_data.enabled = monitor->shared_data->active; + status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF; + status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON; + Debug( 2, "L:%d, D:%d, P:%d, R:%d, d:%.3f, Z:%d, E:%d F:%d", + status_data.buffer_level, + status_data.delayed, + status_data.paused, + status_data.rate, + status_data.delay, + status_data.zoom, + status_data.enabled, + status_data.forced + ); + + DataMsg status_msg; + status_msg.msg_type = MSG_DATA_WATCH; + memcpy( &status_msg.msg_data, &status_data, sizeof(status_data) ); + int nbytes = 0; + if ( (nbytes = sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) )) < 0 ) + { + //if ( errno != EAGAIN ) + { + Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); + //exit( -1 ); + } + } + + // quit after sending a status, if this was a quit request + if ((MsgCommand)msg->msg_data[0]==CMD_QUIT) + exit(0); + + updateFrameRate( monitor->GetFPS() ); } bool MonitorStream::sendFrame( const char *filepath, struct timeval *timestamp ) { - bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); + bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); - if ( type != STREAM_JPEG ) - send_raw = false; - if ( !config.timestamp_on_capture && timestamp ) - send_raw = false; + if ( type != STREAM_JPEG ) + send_raw = false; + if ( !config.timestamp_on_capture && timestamp ) + send_raw = false; - if ( !send_raw ) + if ( !send_raw ) + { + Image temp_image( filepath ); + + return( sendFrame( &temp_image, timestamp ) ); + } + else + { + int img_buffer_size = 0; + static unsigned char img_buffer[ZM_MAX_IMAGE_SIZE]; + + FILE *fdj = NULL; + if ( (fdj = fopen( filepath, "r" )) ) { - Image temp_image( filepath ); - - return( sendFrame( &temp_image, timestamp ) ); + img_buffer_size = fread( img_buffer, 1, sizeof(img_buffer), fdj ); + fclose( fdj ); } else { - int img_buffer_size = 0; - static unsigned char img_buffer[ZM_MAX_IMAGE_SIZE]; - - FILE *fdj = NULL; - if ( (fdj = fopen( filepath, "r" )) ) - { - img_buffer_size = fread( img_buffer, 1, sizeof(img_buffer), fdj ); - fclose( fdj ); - } - else - { - Error( "Can't open %s: %s", filepath, strerror(errno) ); - return( false ); - } - - // Calculate how long it takes to actually send the frame - struct timeval frameStartTime; - gettimeofday( &frameStartTime, NULL ); - - fprintf( stdout, "--ZoneMinderFrame\r\n" ); - fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); - fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) - { - if ( !zm_terminate ) - Error( "Unable to send stream frame: %s", strerror(errno) ); - return( false ); - } - fprintf( stdout, "\r\n\r\n" ); - fflush( stdout ); - - struct timeval frameEndTime; - gettimeofday( &frameEndTime, NULL ); - - int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); - if ( frameSendTime > 1000/maxfps ) - { - maxfps /= 2; - Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); - } - - last_frame_sent = TV_2_FLOAT( now ); - - return( true ); + Error( "Can't open %s: %s", filepath, strerror(errno) ); + return( false ); } - return( false ); + + // Calculate how long it takes to actually send the frame + struct timeval frameStartTime; + gettimeofday( &frameStartTime, NULL ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + if ( !zm_terminate ) + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + + struct timeval frameEndTime; + gettimeofday( &frameEndTime, NULL ); + + int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + if ( frameSendTime > 1000/maxfps ) + { + maxfps /= 2; + Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); + } + + last_frame_sent = TV_2_FLOAT( now ); + + return( true ); + } + return( false ); } bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) { - Image *send_image = prepareImage( image ); - if ( !config.timestamp_on_capture && timestamp ) - monitor->TimestampImage( send_image, timestamp ); + Image *send_image = prepareImage( image ); + if ( !config.timestamp_on_capture && timestamp ) + monitor->TimestampImage( send_image, timestamp ); #if HAVE_LIBAVCODEC - if ( type == STREAM_MPEG ) + if ( type == STREAM_MPEG ) + { + if ( !vid_stream ) { - if ( !vid_stream ) - { - vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); - fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); - vid_stream->OpenStream(); - } - static struct timeval base_time; - struct DeltaTimeval delta_time; - if ( !frame_count ) - base_time = *timestamp; - DELTA_TIMEVAL( delta_time, *timestamp, base_time, DT_PREC_3 ); - /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.delta ); + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); } - else + static struct timeval base_time; + struct DeltaTimeval delta_time; + if ( !frame_count ) + base_time = *timestamp; + DELTA_TIMEVAL( delta_time, *timestamp, base_time, DT_PREC_3 ); + /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.delta ); + } + else #endif // HAVE_LIBAVCODEC + { + static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; + + int img_buffer_size = 0; + unsigned char *img_buffer = temp_img_buffer; + + // Calculate how long it takes to actually send the frame + struct timeval frameStartTime; + gettimeofday( &frameStartTime, NULL ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + switch( type ) { - static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; - - int img_buffer_size = 0; - unsigned char *img_buffer = temp_img_buffer; - - // Calculate how long it takes to actually send the frame - struct timeval frameStartTime; - gettimeofday( &frameStartTime, NULL ); - - fprintf( stdout, "--ZoneMinderFrame\r\n" ); - switch( type ) - { - case STREAM_JPEG : - send_image->EncodeJpeg( img_buffer, &img_buffer_size ); - fprintf( stdout, "Content-Type: image/jpeg\r\n" ); - break; - case STREAM_RAW : - fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); - img_buffer = (uint8_t*)send_image->Buffer(); - img_buffer_size = send_image->Size(); - break; - case STREAM_ZIP : - fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); - unsigned long zip_buffer_size; - send_image->Zip( img_buffer, &zip_buffer_size ); - img_buffer_size = zip_buffer_size; - break; - default : - Fatal( "Unexpected frame type %d", type ); - break; - } - fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); - if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) - { - if ( !zm_terminate ) - Error( "Unable to send stream frame: %s", strerror(errno) ); - return( false ); - } - fprintf( stdout, "\r\n\r\n" ); - fflush( stdout ); - - struct timeval frameEndTime; - gettimeofday( &frameEndTime, NULL ); - - int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); - if ( frameSendTime > 1000/maxfps ) - { - maxfps /= 1.5; - Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); - } + case STREAM_JPEG : + send_image->EncodeJpeg( img_buffer, &img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n" ); + break; + case STREAM_RAW : + fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); + img_buffer = (uint8_t*)send_image->Buffer(); + img_buffer_size = send_image->Size(); + break; + case STREAM_ZIP : + fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); + unsigned long zip_buffer_size; + send_image->Zip( img_buffer, &zip_buffer_size ); + img_buffer_size = zip_buffer_size; + break; + default : + Fatal( "Unexpected frame type %d", type ); + break; } - last_frame_sent = TV_2_FLOAT( now ); - return( true ); + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + if ( !zm_terminate ) + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + + struct timeval frameEndTime; + gettimeofday( &frameEndTime, NULL ); + + int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + if ( frameSendTime > 1000/maxfps ) + { + maxfps /= 1.5; + Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); + } + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); } void MonitorStream::runStream() { - if ( type == STREAM_SINGLE ) + if ( type == STREAM_SINGLE ) + { + // Not yet migrated over to stream class + monitor->SingleImage( scale ); + return; + } + + openComms(); + + checkInitialised(); + + updateFrameRate( monitor->GetFPS() ); + + if ( type == STREAM_JPEG ) + fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); + + int last_read_index = monitor->image_buffer_count; + + time_t stream_start_time; + time( &stream_start_time ); + + frame_count = 0; + + temp_image_buffer = 0; + temp_image_buffer_count = playback_buffer; + temp_read_index = temp_image_buffer_count; + temp_write_index = temp_image_buffer_count; + + char *swap_path = 0; + bool buffered_playback = false; + + // 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id + const int max_swap_len_suffix = 15; + + int swap_path_length = strlen(config.path_swap)+1; // +1 for NULL terminator + + if ( connkey && playback_buffer > 0 ) { + + if ( swap_path_length + max_swap_len_suffix > PATH_MAX ) { + Error( "Swap Path is too long. %d > %d ", swap_path_length+max_swap_len_suffix, PATH_MAX ); + } else { + swap_path = (char *)malloc( swap_path_length+max_swap_len_suffix ); + Debug( 3, "Checking swap image path %s", config.path_swap ); + strncpy( swap_path, config.path_swap, swap_path_length ); + if ( checkSwapPath( swap_path, false ) ) { + snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-m%d", monitor->Id() ); + if ( checkSwapPath( swap_path, true ) ) { + snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-q%06d", connkey ); + if ( checkSwapPath( swap_path, true ) ) { + buffered_playback = true; + } + } + } + + if ( !buffered_playback ) { + Error( "Unable to validate swap image path, disabling buffered playback" ); + } else { + Debug( 2, "Assigning temporary buffer" ); + temp_image_buffer = new SwapImage[temp_image_buffer_count]; + memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count ); + Debug( 2, "Assigned temporary buffer" ); + } + } + } + + float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) + while ( !zm_terminate ) + { + bool got_command = false; + if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) { - // Not yet migrated over to stream class - monitor->SingleImage( scale ); - return; + break; } - openComms(); + gettimeofday( &now, NULL ); - checkInitialised(); - - updateFrameRate( monitor->GetFPS() ); - - if ( type == STREAM_JPEG ) - fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); - - int last_read_index = monitor->image_buffer_count; - - time_t stream_start_time; - time( &stream_start_time ); - - frame_count = 0; - - temp_image_buffer = 0; - temp_image_buffer_count = playback_buffer; - temp_read_index = temp_image_buffer_count; - temp_write_index = temp_image_buffer_count; - - char *swap_path = 0; - bool buffered_playback = false; - - // 15 is the max length for the swap path suffix, /zmswap-whatever, assuming max 6 digits for monitor id - const int max_swap_len_suffix = 15; - - int swap_path_length = strlen(config.path_swap)+1; // +1 for NULL terminator - - if ( connkey && playback_buffer > 0 ) { - - if ( swap_path_length + max_swap_len_suffix > PATH_MAX ) { - Error( "Swap Path is too long. %d > %d ", swap_path_length+max_swap_len_suffix, PATH_MAX ); - } else { - swap_path = (char *)malloc( swap_path_length+max_swap_len_suffix ); - Debug( 3, "Checking swap image path %s", config.path_swap ); - strncpy( swap_path, config.path_swap, swap_path_length ); - if ( checkSwapPath( swap_path, false ) ) { - snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-m%d", monitor->Id() ); - if ( checkSwapPath( swap_path, true ) ) { - snprintf( &(swap_path[swap_path_length]), max_swap_len_suffix, "/zmswap-q%06d", connkey ); - if ( checkSwapPath( swap_path, true ) ) { - buffered_playback = true; - } - } - } - - if ( !buffered_playback ) { - Error( "Unable to validate swap image path, disabling buffered playback" ); - } else { - Debug( 2, "Assigning temporary buffer" ); - temp_image_buffer = new SwapImage[temp_image_buffer_count]; - memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count ); - Debug( 2, "Assigned temporary buffer" ); - } - } + if ( connkey ) + { + while(checkCommandQueue()) { + got_command = true; + } } - float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) - while ( !zm_terminate ) + //bool frame_sent = false; + if ( buffered_playback && delayed ) { - bool got_command = false; - if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) + if ( temp_read_index == temp_write_index ) + { + // Go back to live viewing + Debug( 1, "Exceeded temporary streaming buffer" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + else + { + if ( !paused ) { - break; - } + int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); + //Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index ); + SwapImage *swap_image = &temp_image_buffer[temp_index]; - gettimeofday( &now, NULL ); + if ( !swap_image->valid ) + { + paused = true; + delayed = true; + temp_read_index = MOD_ADD( temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count ); + } + else + { + //Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) ); + double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate; + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; - if ( connkey ) - { - while(checkCommandQueue()) { - got_command = true; - } - } - - //bool frame_sent = false; - if ( buffered_playback && delayed ) - { - if ( temp_read_index == temp_write_index ) + //Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) ); + // If the next frame is due + if ( actual_delta_time > expected_delta_time ) { - // Go back to live viewing - Debug( 1, "Exceeded temporary streaming buffer" ); - // Clear paused flag - paused = false; - // Clear delayed_play flag - delayed = false; - replay_rate = ZM_RATE_BASE; - } - else - { - if ( !paused ) - { - int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); - //Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index ); - SwapImage *swap_image = &temp_image_buffer[temp_index]; - - if ( !swap_image->valid ) - { - paused = true; - delayed = true; - temp_read_index = MOD_ADD( temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count ); - } - else - { - //Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) ); - double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate; - double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; - - //Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) ); - // If the next frame is due - if ( actual_delta_time > expected_delta_time ) - { - //Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time ); - if ( temp_index%frame_mod == 0 ) - { - Debug( 2, "Sending delayed frame %d", temp_index ); - // Send the next frame - if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) - zm_terminate = true; - memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); - //frame_sent = true; - } - temp_read_index = MOD_ADD( temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count ); - } - } - } - else if ( step != 0 ) - { - temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count ); - - SwapImage *swap_image = &temp_image_buffer[temp_read_index]; - - // Send the next frame - if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) ) - zm_terminate = true; - memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); - //frame_sent = true; - step = 0; - } - else - { - int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); - - double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; - if ( got_command || actual_delta_time > 5 ) - { - // Send keepalive - Debug( 2, "Sending keepalive frame %d", temp_index ); - // Send the next frame - if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) - zm_terminate = true; - //frame_sent = true; - } - } - } - if ( temp_read_index == temp_write_index ) - { - // Go back to live viewing - Warning( "Rewound over write index, resuming live play" ); - // Clear paused flag - paused = false; - // Clear delayed_play flag - delayed = false; - replay_rate = ZM_RATE_BASE; + //Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time ); + if ( temp_index%frame_mod == 0 ) + { + Debug( 2, "Sending delayed frame %d", temp_index ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); + //frame_sent = true; + } + temp_read_index = MOD_ADD( temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count ); } + } } - if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) + else if ( step != 0 ) { - int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; - last_read_index = monitor->shared_data->last_write_index; - //Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ); - if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) - { - if ( !paused && !delayed ) - { - // Send the next frame - Monitor::Snapshot *snap = &monitor->image_buffer[index]; + temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count ); - if ( !sendFrame( snap->image, snap->timestamp ) ) - zm_terminate = true; - memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); - //frame_sent = true; + SwapImage *swap_image = &temp_image_buffer[temp_read_index]; - temp_read_index = temp_write_index; - } - } - if ( buffered_playback ) - { - if ( monitor->shared_data->valid ) - { - if ( monitor->image_buffer[index].timestamp->tv_sec ) - { - int temp_index = temp_write_index%temp_image_buffer_count; - Debug( 2, "Storing frame %d", temp_index ); - if ( !temp_image_buffer[temp_index].valid ) - { - snprintf( temp_image_buffer[temp_index].file_name, sizeof(temp_image_buffer[0].file_name), "%s/zmswap-i%05d.jpg", swap_path, temp_index ); - temp_image_buffer[temp_index].valid = true; - } - memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) ); - monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality ); - temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count ); - if ( temp_write_index == temp_read_index ) - { - // Go back to live viewing - Warning( "Exceeded temporary buffer, resuming live play" ); - // Clear paused flag - paused = false; - // Clear delayed_play flag - delayed = false; - replay_rate = ZM_RATE_BASE; - } - } - else - { - Warning( "Unable to store frame as timestamp invalid" ); - } - } - else - { - Warning( "Unable to store frame as shared memory invalid" ); - } - } - frame_count++; - } - usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); - if ( ttl ) - { - if ( (now.tv_sec - stream_start_time) > ttl ) - { - break; - } - } - if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) - { - Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame ); - break; - } - } - if ( buffered_playback ) - { - char swap_path[PATH_MAX] = ""; - - snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", config.path_swap, monitor->Id(), connkey ); - Debug( 1, "Cleaning swap files from %s", swap_path ); - struct stat stat_buf; - if ( stat( swap_path, &stat_buf ) < 0 ) - { - if ( errno != ENOENT ) - { - Error( "Can't stat '%s': %s", swap_path, strerror(errno) ); - } - } - else if ( !S_ISDIR(stat_buf.st_mode) ) - { - Error( "Swap image path '%s' is not a directory", swap_path ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); + //frame_sent = true; + step = 0; } else { - char glob_pattern[PATH_MAX] = ""; + int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); - snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.*", swap_path ); - glob_t pglob; - int glob_status = glob( glob_pattern, 0, 0, &pglob ); - if ( glob_status != 0 ) - { - if ( glob_status < 0 ) - { - Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) ); - } - else - { - Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status ); - } - } - else - { - for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) - { - if ( unlink( pglob.gl_pathv[i] ) < 0 ) - { - Error( "Can't unlink '%s': %s", pglob.gl_pathv[i], strerror(errno) ); - } - } - } - globfree( &pglob ); - if ( rmdir( swap_path ) < 0 ) - { - Error( "Can't rmdir '%s': %s", swap_path, strerror(errno) ); - } + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( got_command || actual_delta_time > 5 ) + { + // Send keepalive + Debug( 2, "Sending keepalive frame %d", temp_index ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) + zm_terminate = true; + //frame_sent = true; + } } + } + if ( temp_read_index == temp_write_index ) + { + // Go back to live viewing + Warning( "Rewound over write index, resuming live play" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } } - if ( swap_path ) free( swap_path ); - closeComms(); + if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) + { + int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; + last_read_index = monitor->shared_data->last_write_index; + //Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ); + if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) + { + if ( !paused && !delayed ) + { + // Send the next frame + Monitor::Snapshot *snap = &monitor->image_buffer[index]; + + if ( !sendFrame( snap->image, snap->timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); + //frame_sent = true; + + temp_read_index = temp_write_index; + } + } + if ( buffered_playback ) + { + if ( monitor->shared_data->valid ) + { + if ( monitor->image_buffer[index].timestamp->tv_sec ) + { + int temp_index = temp_write_index%temp_image_buffer_count; + Debug( 2, "Storing frame %d", temp_index ); + if ( !temp_image_buffer[temp_index].valid ) + { + snprintf( temp_image_buffer[temp_index].file_name, sizeof(temp_image_buffer[0].file_name), "%s/zmswap-i%05d.jpg", swap_path, temp_index ); + temp_image_buffer[temp_index].valid = true; + } + memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) ); + monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality ); + temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count ); + if ( temp_write_index == temp_read_index ) + { + // Go back to live viewing + Warning( "Exceeded temporary buffer, resuming live play" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + } + else + { + Warning( "Unable to store frame as timestamp invalid" ); + } + } + else + { + Warning( "Unable to store frame as shared memory invalid" ); + } + } + frame_count++; + } + usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); + if ( ttl ) + { + if ( (now.tv_sec - stream_start_time) > ttl ) + { + break; + } + } + if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) + { + Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame ); + break; + } + } + if ( buffered_playback ) + { + char swap_path[PATH_MAX] = ""; + + snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", config.path_swap, monitor->Id(), connkey ); + Debug( 1, "Cleaning swap files from %s", swap_path ); + struct stat stat_buf; + if ( stat( swap_path, &stat_buf ) < 0 ) + { + if ( errno != ENOENT ) + { + Error( "Can't stat '%s': %s", swap_path, strerror(errno) ); + } + } + else if ( !S_ISDIR(stat_buf.st_mode) ) + { + Error( "Swap image path '%s' is not a directory", swap_path ); + } + else + { + char glob_pattern[PATH_MAX] = ""; + + snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.*", swap_path ); + glob_t pglob; + int glob_status = glob( glob_pattern, 0, 0, &pglob ); + if ( glob_status != 0 ) + { + if ( glob_status < 0 ) + { + Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) ); + } + else + { + Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status ); + } + } + else + { + for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) + { + if ( unlink( pglob.gl_pathv[i] ) < 0 ) + { + Error( "Can't unlink '%s': %s", pglob.gl_pathv[i], strerror(errno) ); + } + } + } + globfree( &pglob ); + if ( rmdir( swap_path ) < 0 ) + { + Error( "Can't rmdir '%s': %s", swap_path, strerror(errno) ); + } + } + } + if ( swap_path ) free( swap_path ); + closeComms(); } void Monitor::SingleImage( int scale) { - int img_buffer_size = 0; - static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; - Image scaled_image; - int index = shared_data->last_write_index%image_buffer_count; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + int img_buffer_size = 0; + static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - if ( scale != ZM_SCALE_BASE ) - { - scaled_image.Assign( *snap_image ); - scaled_image.Scale( scale ); - snap_image = &scaled_image; - } - if ( !config.timestamp_on_capture ) - { - TimestampImage( snap_image, snap->timestamp ); - } - snap_image->EncodeJpeg( img_buffer, &img_buffer_size ); - - fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); - fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); - fwrite( img_buffer, img_buffer_size, 1, stdout ); + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->EncodeJpeg( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); } void Monitor::SingleImageRaw( int scale) { - Image scaled_image; - int index = shared_data->last_write_index%image_buffer_count; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - if ( scale != ZM_SCALE_BASE ) - { - scaled_image.Assign( *snap_image ); - scaled_image.Scale( scale ); - snap_image = &scaled_image; - } - if ( !config.timestamp_on_capture ) - { - TimestampImage( snap_image, snap->timestamp ); - } - - fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() ); - fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); - fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + + fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() ); + fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); + fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); } void Monitor::SingleImageZip( int scale) { - unsigned long img_buffer_size = 0; - static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; - Image scaled_image; - int index = shared_data->last_write_index%image_buffer_count; - Snapshot *snap = &image_buffer[index]; - Image *snap_image = snap->image; + unsigned long img_buffer_size = 0; + static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; - if ( scale != ZM_SCALE_BASE ) - { - scaled_image.Assign( *snap_image ); - scaled_image.Scale( scale ); - snap_image = &scaled_image; - } - if ( !config.timestamp_on_capture ) - { - TimestampImage( snap_image, snap->timestamp ); - } - snap_image->Zip( img_buffer, &img_buffer_size ); - - fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); - fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); - fwrite( img_buffer, img_buffer_size, 1, stdout ); + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->Zip( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); } diff --git a/src/zm_monitor.h b/src/zm_monitor.h index a9cd05674..57fd7a369 100644 --- a/src/zm_monitor.h +++ b/src/zm_monitor.h @@ -50,396 +50,396 @@ class Monitor friend class MonitorStream; public: - typedef enum - { - QUERY=0, - CAPTURE, - ANALYSIS - } Purpose; + typedef enum + { + QUERY=0, + CAPTURE, + ANALYSIS + } Purpose; - typedef enum - { - NONE=1, - MONITOR, - MODECT, - RECORD, - MOCORD, - NODECT - } Function; + typedef enum + { + NONE=1, + MONITOR, + MODECT, + RECORD, + MOCORD, + NODECT + } Function; - typedef enum - { - ROTATE_0=1, - ROTATE_90, - ROTATE_180, - ROTATE_270, - FLIP_HORI, - FLIP_VERT - } Orientation; + typedef enum + { + ROTATE_0=1, + ROTATE_90, + ROTATE_180, + ROTATE_270, + FLIP_HORI, + FLIP_VERT + } Orientation; - typedef enum - { - IDLE, - PREALARM, - ALARM, - ALERT, - TAPE - } State; + typedef enum + { + IDLE, + PREALARM, + ALARM, + ALERT, + TAPE + } State; protected: - typedef std::set ZoneSet; + typedef std::set ZoneSet; - typedef enum { GET_SETTINGS=0x1, SET_SETTINGS=0x2, RELOAD=0x4, SUSPEND=0x10, RESUME=0x20 } Action; + typedef enum { GET_SETTINGS=0x1, SET_SETTINGS=0x2, RELOAD=0x4, SUSPEND=0x10, RESUME=0x20 } Action; - typedef enum { CLOSE_TIME, CLOSE_IDLE, CLOSE_ALARM } EventCloseMode; + typedef enum { CLOSE_TIME, CLOSE_IDLE, CLOSE_ALARM } EventCloseMode; - /* sizeof(SharedData) expected to be 336 bytes on 32bit and 64bit */ - typedef struct - { - uint32_t size; /* +0 */ - uint32_t last_write_index; /* +4 */ - uint32_t last_read_index; /* +8 */ - uint32_t state; /* +12 */ - uint32_t last_event; /* +16 */ - uint32_t action; /* +20 */ - int32_t brightness; /* +24 */ - int32_t hue; /* +28 */ - int32_t colour; /* +32 */ - int32_t contrast; /* +36 */ - int32_t alarm_x; /* +40 */ - int32_t alarm_y; /* +44 */ - uint8_t valid; /* +48 */ - uint8_t active; /* +49 */ - uint8_t signal; /* +50 */ - uint8_t format; /* +51 */ - uint32_t imagesize; /* +52 */ - uint32_t epadding1; /* +56 */ - uint32_t epadding2; /* +60 */ - /* - ** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038. - ** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16. - */ - union { /* +64 */ - time_t last_write_time; - uint64_t extrapad1; - }; - union { /* +72 */ - time_t last_read_time; - uint64_t extrapad2; - }; - uint8_t control_state[256]; /* +80 */ - - } SharedData; + /* sizeof(SharedData) expected to be 336 bytes on 32bit and 64bit */ + typedef struct + { + uint32_t size; /* +0 */ + uint32_t last_write_index; /* +4 */ + uint32_t last_read_index; /* +8 */ + uint32_t state; /* +12 */ + uint32_t last_event; /* +16 */ + uint32_t action; /* +20 */ + int32_t brightness; /* +24 */ + int32_t hue; /* +28 */ + int32_t colour; /* +32 */ + int32_t contrast; /* +36 */ + int32_t alarm_x; /* +40 */ + int32_t alarm_y; /* +44 */ + uint8_t valid; /* +48 */ + uint8_t active; /* +49 */ + uint8_t signal; /* +50 */ + uint8_t format; /* +51 */ + uint32_t imagesize; /* +52 */ + uint32_t epadding1; /* +56 */ + uint32_t epadding2; /* +60 */ + /* + ** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038. + ** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16. + */ + union { /* +64 */ + time_t last_write_time; + uint64_t extrapad1; + }; + union { /* +72 */ + time_t last_read_time; + uint64_t extrapad2; + }; + uint8_t control_state[256]; /* +80 */ + + } SharedData; - typedef enum { TRIGGER_CANCEL, TRIGGER_ON, TRIGGER_OFF } TriggerState; - - /* sizeof(TriggerData) expected to be 560 on 32bit & and 64bit */ - typedef struct - { - uint32_t size; - uint32_t trigger_state; - uint32_t trigger_score; - uint32_t padding; - char trigger_cause[32]; - char trigger_text[256]; - char trigger_showtext[256]; - } TriggerData; + typedef enum { TRIGGER_CANCEL, TRIGGER_ON, TRIGGER_OFF } TriggerState; + + /* sizeof(TriggerData) expected to be 560 on 32bit & and 64bit */ + typedef struct + { + uint32_t size; + uint32_t trigger_state; + uint32_t trigger_score; + uint32_t padding; + char trigger_cause[32]; + char trigger_text[256]; + char trigger_showtext[256]; + } TriggerData; - /* sizeof(Snapshot) expected to be 16 bytes on 32bit and 32 bytes on 64bit */ - struct Snapshot - { - struct timeval *timestamp; - Image *image; - void* padding; - }; + /* sizeof(Snapshot) expected to be 16 bytes on 32bit and 32 bytes on 64bit */ + struct Snapshot + { + struct timeval *timestamp; + Image *image; + void* padding; + }; - class MonitorLink - { - protected: - unsigned int id; - char name[64]; + class MonitorLink + { + protected: + unsigned int id; + char name[64]; - bool connected; - time_t last_connect_time; + bool connected; + time_t last_connect_time; #if ZM_MEM_MAPPED - int map_fd; - char mem_file[PATH_MAX]; + int map_fd; + char mem_file[PATH_MAX]; #else // ZM_MEM_MAPPED - int shm_id; + int shm_id; #endif // ZM_MEM_MAPPED - off_t mem_size; - unsigned char *mem_ptr; + off_t mem_size; + unsigned char *mem_ptr; - volatile SharedData *shared_data; - volatile TriggerData *trigger_data; + volatile SharedData *shared_data; + volatile TriggerData *trigger_data; - int last_state; - int last_event; + int last_state; + int last_event; - public: - MonitorLink( int p_id, const char *p_name ); - ~MonitorLink(); + public: + MonitorLink( int p_id, const char *p_name ); + ~MonitorLink(); - inline int Id() const - { - return( id ); - } - inline const char *Name() const - { - return( name ); - } + inline int Id() const + { + return( id ); + } + inline const char *Name() const + { + return( name ); + } - inline bool isConnected() const - { - return( connected ); - } - inline time_t getLastConnectTime() const - { - return( last_connect_time ); - } + inline bool isConnected() const + { + return( connected ); + } + inline time_t getLastConnectTime() const + { + return( last_connect_time ); + } - bool connect(); - bool disconnect(); + bool connect(); + bool disconnect(); - bool isAlarmed(); - bool inAlarm(); - bool hasAlarmed(); - }; + bool isAlarmed(); + bool inAlarm(); + bool hasAlarmed(); + }; protected: - // These are read from the DB and thereafter remain unchanged - unsigned int id; - char name[64]; - unsigned int server_id; - Function function; // What the monitor is doing - bool enabled; // Whether the monitor is enabled or asleep - unsigned int width; // Normally the same as the camera, but not if partly rotated - unsigned int height; // Normally the same as the camera, but not if partly rotated - bool v4l_multi_buffer; - unsigned int v4l_captures_per_frame; - Orientation orientation; // Whether the image has to be rotated at all - unsigned int deinterlacing; - int brightness; // The statically saved brightness of the camera - int contrast; // The statically saved contrast of the camera - int hue; // The statically saved hue of the camera - int colour; // The statically saved colour of the camera - char event_prefix[64]; // The prefix applied to event names as they are created - char label_format[64]; // The format of the timestamp on the images - Coord label_coord; // The coordinates of the timestamp on the images - int label_size; // Size of the timestamp on the images - int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count - int pre_event_buffer_count; // Size of dedicated circular pre event buffer used when analysis is not performed at capturing framerate, - // value is pre_event_count + alarm_frame_count - 1 - int warmup_count; // How many images to process before looking for events - int pre_event_count; // How many images to hold and prepend to an alarm event - int post_event_count; // How many unalarmed images must occur before the alarm state is reset - int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now - int section_length; // How long events should last in continuous modes - bool adaptive_skip; // Whether to use the newer adaptive algorithm for this monitor - int frame_skip; // How many frames to skip in continuous modes - int motion_frame_skip; // How many frames to skip in motion detection - double analysis_fps; // Target framerate for video analysis - unsigned int analysis_update_delay; // How long we wait before updating analysis parameters - int capture_delay; // How long we wait between capture frames - int alarm_capture_delay; // How long we wait between capture frames when in alarm state - int alarm_frame_count; // How many alarm frames are required before an event is triggered - int fps_report_interval; // How many images should be captured/processed between reporting the current FPS - int ref_blend_perc; // Percentage of new image going into reference image. - int alarm_ref_blend_perc; // Percentage of new image going into reference image during alarm. - bool track_motion; // Whether this monitor tries to track detected motion - Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected - bool embed_exif; // Whether to embed Exif data into each image frame or not + // These are read from the DB and thereafter remain unchanged + unsigned int id; + char name[64]; + unsigned int server_id; + Function function; // What the monitor is doing + bool enabled; // Whether the monitor is enabled or asleep + unsigned int width; // Normally the same as the camera, but not if partly rotated + unsigned int height; // Normally the same as the camera, but not if partly rotated + bool v4l_multi_buffer; + unsigned int v4l_captures_per_frame; + Orientation orientation; // Whether the image has to be rotated at all + unsigned int deinterlacing; + int brightness; // The statically saved brightness of the camera + int contrast; // The statically saved contrast of the camera + int hue; // The statically saved hue of the camera + int colour; // The statically saved colour of the camera + char event_prefix[64]; // The prefix applied to event names as they are created + char label_format[64]; // The format of the timestamp on the images + Coord label_coord; // The coordinates of the timestamp on the images + int label_size; // Size of the timestamp on the images + int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count + int pre_event_buffer_count; // Size of dedicated circular pre event buffer used when analysis is not performed at capturing framerate, + // value is pre_event_count + alarm_frame_count - 1 + int warmup_count; // How many images to process before looking for events + int pre_event_count; // How many images to hold and prepend to an alarm event + int post_event_count; // How many unalarmed images must occur before the alarm state is reset + int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now + int section_length; // How long events should last in continuous modes + bool adaptive_skip; // Whether to use the newer adaptive algorithm for this monitor + int frame_skip; // How many frames to skip in continuous modes + int motion_frame_skip; // How many frames to skip in motion detection + double analysis_fps; // Target framerate for video analysis + unsigned int analysis_update_delay; // How long we wait before updating analysis parameters + int capture_delay; // How long we wait between capture frames + int alarm_capture_delay; // How long we wait between capture frames when in alarm state + int alarm_frame_count; // How many alarm frames are required before an event is triggered + int fps_report_interval; // How many images should be captured/processed between reporting the current FPS + int ref_blend_perc; // Percentage of new image going into reference image. + int alarm_ref_blend_perc; // Percentage of new image going into reference image during alarm. + bool track_motion; // Whether this monitor tries to track detected motion + Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected + bool embed_exif; // Whether to embed Exif data into each image frame or not - double fps; - Image delta_image; - Image ref_image; - Image alarm_image; // Used in creating analysis images, will be initialized in Analysis - Image write_image; // Used when creating snapshot images + double fps; + Image delta_image; + Image ref_image; + Image alarm_image; // Used in creating analysis images, will be initialized in Analysis + Image write_image; // Used when creating snapshot images - Purpose purpose; // What this monitor has been created to do - int event_count; - int image_count; - int ready_count; - int first_alarm_count; - int last_alarm_count; - int buffer_count; - int prealarm_count; - State state; - time_t start_time; - time_t last_fps_time; - time_t auto_resume_time; - unsigned int last_motion_score; + Purpose purpose; // What this monitor has been created to do + int event_count; + int image_count; + int ready_count; + int first_alarm_count; + int last_alarm_count; + int buffer_count; + int prealarm_count; + State state; + time_t start_time; + time_t last_fps_time; + time_t auto_resume_time; + unsigned int last_motion_score; - EventCloseMode event_close_mode; + EventCloseMode event_close_mode; #if ZM_MEM_MAPPED - int map_fd; - char mem_file[PATH_MAX]; + int map_fd; + char mem_file[PATH_MAX]; #else // ZM_MEM_MAPPED - int shm_id; + int shm_id; #endif // ZM_MEM_MAPPED - off_t mem_size; - unsigned char *mem_ptr; + off_t mem_size; + unsigned char *mem_ptr; - SharedData *shared_data; - TriggerData *trigger_data; + SharedData *shared_data; + TriggerData *trigger_data; - Snapshot *image_buffer; - Snapshot next_buffer; /* Used by four field deinterlacing */ - Snapshot *pre_event_buffer; + Snapshot *image_buffer; + Snapshot next_buffer; /* Used by four field deinterlacing */ + Snapshot *pre_event_buffer; - Camera *camera; + Camera *camera; - Event *event; + Event *event; - int n_zones; - Zone **zones; + int n_zones; + Zone **zones; - struct timeval **timestamps; - Image **images; + struct timeval **timestamps; + Image **images; - const unsigned char *privacy_bitmask; + const unsigned char *privacy_bitmask; - int n_linked_monitors; - MonitorLink **linked_monitors; + int n_linked_monitors; + MonitorLink **linked_monitors; public: // OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info. //bool OurCheckAlarms( Zone *zone, const Image *pImage ); - Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 ); - ~Monitor(); + Monitor( int p_id, const char *p_name, unsigned int p_server_id, int p_function, bool p_enabled, const char *p_linked_monitors, Camera *p_camera, int p_orientation, unsigned int p_deinterlacing, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, int label_size, int p_image_buffer_count, int p_warmup_count, int p_pre_event_count, int p_post_event_count, int p_stream_replay_buffer, int p_alarm_frame_count, int p_section_length, int p_frame_skip, int p_motion_frame_skip, double p_analysis_fps, unsigned int p_analysis_update_delay, int p_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, int p_alarm_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, bool p_embed_exif, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 ); + ~Monitor(); - void AddZones( int p_n_zones, Zone *p_zones[] ); - void AddPrivacyBitmask( Zone *p_zones[] ); + void AddZones( int p_n_zones, Zone *p_zones[] ); + void AddPrivacyBitmask( Zone *p_zones[] ); - bool connect(); - inline int ShmValid() const - { - return( shared_data->valid ); - } + bool connect(); + inline int ShmValid() const + { + return( shared_data->valid ); + } - inline int Id() const - { - return( id ); - } - inline const char *Name() const - { - return( name ); - } - inline Function GetFunction() const - { - return( function ); - } - inline bool Enabled() - { - if ( function <= MONITOR ) - return( false ); - return( enabled ); - } - inline const char *EventPrefix() const - { - return( event_prefix ); - } - inline bool Ready() - { - if ( function <= MONITOR ) - return( false ); - return( image_count > ready_count ); - } - inline bool Active() - { - if ( function <= MONITOR ) - return( false ); - return( enabled && shared_data->active ); - } - inline bool Exif() - { - return( embed_exif ); - } + inline int Id() const + { + return( id ); + } + inline const char *Name() const + { + return( name ); + } + inline Function GetFunction() const + { + return( function ); + } + inline bool Enabled() + { + if ( function <= MONITOR ) + return( false ); + return( enabled ); + } + inline const char *EventPrefix() const + { + return( event_prefix ); + } + inline bool Ready() + { + if ( function <= MONITOR ) + return( false ); + return( image_count > ready_count ); + } + inline bool Active() + { + if ( function <= MONITOR ) + return( false ); + return( enabled && shared_data->active ); + } + inline bool Exif() + { + return( embed_exif ); + } - unsigned int Width() const { return( width ); } - unsigned int Height() const { return( height ); } - unsigned int Colours() const { return( camera->Colours() ); } - unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); } - + unsigned int Width() const { return( width ); } + unsigned int Height() const { return( height ); } + unsigned int Colours() const { return( camera->Colours() ); } + unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); } + - State GetState() const; - int GetImage( int index=-1, int scale=100 ); - struct timeval GetTimestamp( int index=-1 ) const; - void UpdateAdaptiveSkip(); - useconds_t GetAnalysisRate(); - unsigned int GetAnalysisUpdateDelay() const { return( analysis_update_delay ); } - int GetCaptureDelay() const { return( capture_delay ); } - int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); } - unsigned int GetLastReadIndex() const; - unsigned int GetLastWriteIndex() const; - unsigned int GetLastEvent() const; - double GetFPS() const; - void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); - void ForceAlarmOff(); - void CancelForced(); - TriggerState GetTriggerState() const { return( (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL )); } + State GetState() const; + int GetImage( int index=-1, int scale=100 ); + struct timeval GetTimestamp( int index=-1 ) const; + void UpdateAdaptiveSkip(); + useconds_t GetAnalysisRate(); + unsigned int GetAnalysisUpdateDelay() const { return( analysis_update_delay ); } + int GetCaptureDelay() const { return( capture_delay ); } + int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); } + unsigned int GetLastReadIndex() const; + unsigned int GetLastWriteIndex() const; + unsigned int GetLastEvent() const; + double GetFPS() const; + void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); + void ForceAlarmOff(); + void CancelForced(); + TriggerState GetTriggerState() const { return( (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL )); } - void actionReload(); - void actionEnable(); - void actionDisable(); - void actionSuspend(); - void actionResume(); + void actionReload(); + void actionEnable(); + void actionDisable(); + void actionSuspend(); + void actionResume(); - int actionBrightness( int p_brightness=-1 ); - int actionHue( int p_hue=-1 ); - int actionColour( int p_colour=-1 ); - int actionContrast( int p_contrast=-1 ); + int actionBrightness( int p_brightness=-1 ); + int actionHue( int p_hue=-1 ); + int actionColour( int p_colour=-1 ); + int actionContrast( int p_contrast=-1 ); - inline int PrimeCapture() - { - return( camera->PrimeCapture() ); - } - inline int PreCapture() - { - return( camera->PreCapture() ); - } - int Capture(); - int PostCapture() - { - return( camera->PostCapture() ); - } + inline int PrimeCapture() + { + return( camera->PrimeCapture() ); + } + inline int PreCapture() + { + return( camera->PreCapture() ); + } + int Capture(); + int PostCapture() + { + return( camera->PostCapture() ); + } - unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); + unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); // DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info. //unsigned int DetectBlack( const Image &comp_image, Event::StringSet &zoneSet ); - bool CheckSignal( const Image *image ); - bool Analyse(); - void DumpImage( Image *dump_image ) const; - void TimestampImage( Image *ts_image, const struct timeval *ts_time ) const; - bool closeEvent(); + bool CheckSignal( const Image *image ); + bool Analyse(); + void DumpImage( Image *dump_image ) const; + void TimestampImage( Image *ts_image, const struct timeval *ts_time ) const; + bool closeEvent(); - void Reload(); - void ReloadZones(); - void ReloadLinkedMonitors( const char * ); + void Reload(); + void ReloadZones(); + void ReloadLinkedMonitors( const char * ); - bool DumpSettings( char *output, bool verbose ); - void DumpZoneImage( const char *zone_string=0 ); + bool DumpSettings( char *output, bool verbose ); + void DumpZoneImage( const char *zone_string=0 ); #if ZM_HAS_V4L - static int LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ); + static int LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ); #endif // ZM_HAS_V4L - static int LoadRemoteMonitors( const char *protocol, const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose ); - static int LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ); + static int LoadRemoteMonitors( const char *protocol, const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose ); + static int LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ); #if HAVE_LIBAVFORMAT - static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); + static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); #endif // HAVE_LIBAVFORMAT - static Monitor *Load( unsigned int id, bool load_zones, Purpose purpose ); - //void writeStreamImage( Image *image, struct timeval *timestamp, int scale, int mag, int x, int y ); - //void StreamImages( int scale=100, int maxfps=10, time_t ttl=0, int msq_id=0 ); - //void StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 ); - //void StreamImagesZip( int scale=100, int maxfps=10, time_t ttl=0 ); - void SingleImage( int scale=100 ); - void SingleImageRaw( int scale=100 ); - void SingleImageZip( int scale=100 ); + static Monitor *Load( unsigned int id, bool load_zones, Purpose purpose ); + //void writeStreamImage( Image *image, struct timeval *timestamp, int scale, int mag, int x, int y ); + //void StreamImages( int scale=100, int maxfps=10, time_t ttl=0, int msq_id=0 ); + //void StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 ); + //void StreamImagesZip( int scale=100, int maxfps=10, time_t ttl=0 ); + void SingleImage( int scale=100 ); + void SingleImageRaw( int scale=100 ); + void SingleImageZip( int scale=100 ); #if HAVE_LIBAVCODEC - //void StreamMpeg( const char *format, int scale=100, int maxfps=10, int bitrate=100000 ); + //void StreamMpeg( const char *format, int scale=100, int maxfps=10, int bitrate=100000 ); #endif // HAVE_LIBAVCODEC }; @@ -448,51 +448,51 @@ public: class MonitorStream : public StreamBase { protected: - typedef struct SwapImage { - bool valid; - struct timeval timestamp; - char file_name[PATH_MAX]; - } SwapImage; + typedef struct SwapImage { + bool valid; + struct timeval timestamp; + char file_name[PATH_MAX]; + } SwapImage; private: - SwapImage *temp_image_buffer; - int temp_image_buffer_count; - int temp_read_index; - int temp_write_index; + SwapImage *temp_image_buffer; + int temp_image_buffer_count; + int temp_read_index; + int temp_write_index; protected: - time_t ttl; + time_t ttl; protected: - int playback_buffer; - bool delayed; + int playback_buffer; + bool delayed; - int frame_count; + int frame_count; protected: - bool checkSwapPath( const char *path, bool create_path ); + bool checkSwapPath( const char *path, bool create_path ); - bool sendFrame( const char *filepath, struct timeval *timestamp ); - bool sendFrame( Image *image, struct timeval *timestamp ); - void processCommand( const CmdMsg *msg ); + bool sendFrame( const char *filepath, struct timeval *timestamp ); + bool sendFrame( Image *image, struct timeval *timestamp ); + void processCommand( const CmdMsg *msg ); public: - MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) - { - } - void setStreamBuffer( int p_playback_buffer ) - { - playback_buffer = p_playback_buffer; - } - void setStreamTTL( time_t p_ttl ) - { - ttl = p_ttl; - } - bool setStreamStart( int monitor_id ) - { - return loadMonitor( monitor_id ); - } - void runStream(); + MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) + { + } + void setStreamBuffer( int p_playback_buffer ) + { + playback_buffer = p_playback_buffer; + } + void setStreamTTL( time_t p_ttl ) + { + ttl = p_ttl; + } + bool setStreamStart( int monitor_id ) + { + return loadMonitor( monitor_id ); + } + void runStream(); }; #endif // ZM_MONITOR_H diff --git a/src/zm_mpeg.cpp b/src/zm_mpeg.cpp index 01f9006b8..69ca89379 100644 --- a/src/zm_mpeg.cpp +++ b/src/zm_mpeg.cpp @@ -34,242 +34,242 @@ extern "C" bool VideoStream::initialised = false; VideoStream::MimeData VideoStream::mime_data[] = { - { "asf", "video/x-ms-asf" }, - { "swf", "application/x-shockwave-flash" }, - { "flv", "video/x-flv" }, - { "mov", "video/quicktime" } + { "asf", "video/x-ms-asf" }, + { "swf", "application/x-shockwave-flash" }, + { "flv", "video/x-flv" }, + { "mov", "video/quicktime" } }; void VideoStream::Initialise( ) { - if ( logDebugging() ) - av_log_set_level( AV_LOG_DEBUG ); - else - av_log_set_level( AV_LOG_QUIET ); + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); - av_register_all( ); + av_register_all( ); #if LIBAVFORMAT_VERSION_CHECK(53, 13, 0, 19, 0) - avformat_network_init(); + avformat_network_init(); #endif - initialised = true; + initialised = true; } void VideoStream::SetupFormat( ) { - /* allocate the output media context */ - ofc = NULL; + /* allocate the output media context */ + ofc = NULL; #if (LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 2, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) - avformat_alloc_output_context2( &ofc, NULL, format, filename ); + avformat_alloc_output_context2( &ofc, NULL, format, filename ); #else - AVFormatContext *s= avformat_alloc_context(); - if(!s) - { - Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) ); - } + AVFormatContext *s= avformat_alloc_context(); + if(!s) + { + Fatal( "avformat_alloc_context failed %d \"%s\"", (size_t)ofc, av_err2str((size_t)ofc) ); + } - AVOutputFormat *oformat; - if (format) { + AVOutputFormat *oformat; + if (format) { #if LIBAVFORMAT_VERSION_CHECK(52, 45, 0, 45, 0) - oformat = av_guess_format(format, NULL, NULL); + oformat = av_guess_format(format, NULL, NULL); #else - oformat = guess_format(format, NULL, NULL); + oformat = guess_format(format, NULL, NULL); #endif - if (!oformat) { - Fatal( "Requested output format '%s' is not a suitable output format", format ); - } - } else { + if (!oformat) { + Fatal( "Requested output format '%s' is not a suitable output format", format ); + } + } else { #if LIBAVFORMAT_VERSION_CHECK(52, 45, 0, 45, 0) - oformat = av_guess_format(NULL, filename, NULL); + oformat = av_guess_format(NULL, filename, NULL); #else - oformat = guess_format(NULL, filename, NULL); + oformat = guess_format(NULL, filename, NULL); #endif - if (!oformat) { - Fatal( "Unable to find a suitable output format for '%s'", format ); - } - } - s->oformat = oformat; - - if (s->oformat->priv_data_size > 0) { - s->priv_data = av_mallocz(s->oformat->priv_data_size); - if (!s->priv_data) - { - Fatal( "Could not allocate private data for output format." ); - } + if (!oformat) { + Fatal( "Unable to find a suitable output format for '%s'", format ); + } + } + s->oformat = oformat; + + if (s->oformat->priv_data_size > 0) { + s->priv_data = av_mallocz(s->oformat->priv_data_size); + if (!s->priv_data) + { + Fatal( "Could not allocate private data for output format." ); + } #if LIBAVFORMAT_VERSION_CHECK(52, 92, 0, 92, 0) - if (s->oformat->priv_class) { - *(const AVClass**)s->priv_data = s->oformat->priv_class; - av_opt_set_defaults(s->priv_data); - } + if (s->oformat->priv_class) { + *(const AVClass**)s->priv_data = s->oformat->priv_class; + av_opt_set_defaults(s->priv_data); + } #endif - } - else - { - s->priv_data = NULL; - } - - if(filename) - { - snprintf( s->filename, sizeof(s->filename), "%s", filename ); - } - - ofc = s; + } + else + { + s->priv_data = NULL; + } + + if(filename) + { + snprintf( s->filename, sizeof(s->filename), "%s", filename ); + } + + ofc = s; #endif - if ( !ofc ) - { - Fatal( "avformat_alloc_..._context failed: %d", ofc ); - } + if ( !ofc ) + { + Fatal( "avformat_alloc_..._context failed: %d", ofc ); + } - of = ofc->oformat; - Debug( 1, "Using output format: %s (%s)", of->name, of->long_name ); + of = ofc->oformat; + Debug( 1, "Using output format: %s (%s)", of->name, of->long_name ); } void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ) { - /* ffmpeg format matching */ - switch(colours) { - case ZM_COLOUR_RGB24: - { - if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { - /* BGR subpixel order */ - pf = AV_PIX_FMT_BGR24; - } else { - /* Assume RGB subpixel order */ - pf = AV_PIX_FMT_RGB24; - } - break; - } - case ZM_COLOUR_RGB32: - { - if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { - /* ARGB subpixel order */ - pf = AV_PIX_FMT_ARGB; - } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { - /* ABGR subpixel order */ - pf = AV_PIX_FMT_ABGR; - } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { - /* BGRA subpixel order */ - pf = AV_PIX_FMT_BGRA; - } else { - /* Assume RGBA subpixel order */ - pf = AV_PIX_FMT_RGBA; - } - break; - } - case ZM_COLOUR_GRAY8: - pf = AV_PIX_FMT_GRAY8; - break; - default: - Panic("Unexpected colours: %d",colours); - break; - } + /* ffmpeg format matching */ + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + pf = AV_PIX_FMT_BGR24; + } else { + /* Assume RGB subpixel order */ + pf = AV_PIX_FMT_RGB24; + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + pf = AV_PIX_FMT_ARGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + pf = AV_PIX_FMT_ABGR; + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + pf = AV_PIX_FMT_BGRA; + } else { + /* Assume RGBA subpixel order */ + pf = AV_PIX_FMT_RGBA; + } + break; + } + case ZM_COLOUR_GRAY8: + pf = AV_PIX_FMT_GRAY8; + break; + default: + Panic("Unexpected colours: %d",colours); + break; + } - if ( strcmp( "rtp", of->name ) == 0 ) - { - // RTP must have a packet_size. - // Not sure what this value should be really... - ofc->packet_size = width*height; - - if ( of->video_codec == AV_CODEC_ID_NONE) - { - // RTP does not have a default codec in ffmpeg <= 0.8. - of->video_codec = AV_CODEC_ID_MPEG4; - } - } - - _AVCODECID codec_id = of->video_codec; - if ( codec_name ) - { - AVCodec *a = avcodec_find_encoder_by_name(codec_name); - if ( a ) - { - codec_id = a->id; - } - else - { + if ( strcmp( "rtp", of->name ) == 0 ) + { + // RTP must have a packet_size. + // Not sure what this value should be really... + ofc->packet_size = width*height; + + if ( of->video_codec == AV_CODEC_ID_NONE) + { + // RTP does not have a default codec in ffmpeg <= 0.8. + of->video_codec = AV_CODEC_ID_MPEG4; + } + } + + _AVCODECID codec_id = of->video_codec; + if ( codec_name ) + { + AVCodec *a = avcodec_find_encoder_by_name(codec_name); + if ( a ) + { + codec_id = a->id; + } + else + { #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) - Debug( 1, "Could not find codec \"%s\". Using default \"%s\"", codec_name, avcodec_get_name( codec_id ) ); + Debug( 1, "Could not find codec \"%s\". Using default \"%s\"", codec_name, avcodec_get_name( codec_id ) ); #else - Debug( 1, "Could not find codec \"%s\". Using default \"%d\"", codec_name, codec_id ); + Debug( 1, "Could not find codec \"%s\". Using default \"%d\"", codec_name, codec_id ); #endif - } - } + } + } - /* add the video streams using the default format codecs - and initialize the codecs */ - ost = NULL; - if ( codec_id != AV_CODEC_ID_NONE ) - { - codec = avcodec_find_encoder( codec_id ); - if ( !codec ) - { + /* add the video streams using the default format codecs + and initialize the codecs */ + ost = NULL; + if ( codec_id != AV_CODEC_ID_NONE ) + { + codec = avcodec_find_encoder( codec_id ); + if ( !codec ) + { #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) - Fatal( "Could not find encoder for '%s'", avcodec_get_name( codec_id ) ); + Fatal( "Could not find encoder for '%s'", avcodec_get_name( codec_id ) ); #else - Fatal( "Could not find encoder for '%d'", codec_id ); + Fatal( "Could not find encoder for '%d'", codec_id ); #endif - } + } #if (LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 11, 0) && (LIBAVFORMAT_VERSION_MICRO >= 100)) - Debug( 1, "Found encoder for '%s'", avcodec_get_name( codec_id ) ); + Debug( 1, "Found encoder for '%s'", avcodec_get_name( codec_id ) ); #else - Debug( 1, "Found encoder for '%d'", codec_id ); + Debug( 1, "Found encoder for '%d'", codec_id ); #endif #if LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0) - ost = avformat_new_stream( ofc, codec ); + ost = avformat_new_stream( ofc, codec ); #else - ost = av_new_stream( ofc, 0 ); + ost = av_new_stream( ofc, 0 ); #endif - - if ( !ost ) - { - Fatal( "Could not alloc stream" ); - } - ost->id = ofc->nb_streams - 1; + + if ( !ost ) + { + Fatal( "Could not alloc stream" ); + } + ost->id = ofc->nb_streams - 1; - Debug( 1, "Allocated stream" ); + Debug( 1, "Allocated stream" ); - AVCodecContext *c = ost->codec; + AVCodecContext *c = ost->codec; - c->codec_id = codec->id; - c->codec_type = codec->type; + c->codec_id = codec->id; + c->codec_type = codec->type; - c->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P; - if ( bitrate <= 100 ) - { - // Quality based bitrate control (VBR). Scale is 1..31 where 1 is best. - // This gets rid of artifacts in the beginning of the movie; and well, even quality. - c->flags |= CODEC_FLAG_QSCALE; - c->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0))); - } - else - { - c->bit_rate = bitrate; - } + c->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P; + if ( bitrate <= 100 ) + { + // Quality based bitrate control (VBR). Scale is 1..31 where 1 is best. + // This gets rid of artifacts in the beginning of the movie; and well, even quality. + c->flags |= CODEC_FLAG_QSCALE; + c->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0))); + } + else + { + c->bit_rate = bitrate; + } - /* resolution must be a multiple of two */ - c->width = width; - c->height = height; - /* time base: this is the fundamental unit of time (in seconds) in terms - of which frame timestamps are represented. for fixed-fps content, - timebase should be 1/framerate and timestamp increments should be - identically 1. */ - c->time_base.den = frame_rate; - c->time_base.num = 1; - - Debug( 1, "Will encode in %d fps.", c->time_base.den ); - - /* emit one intra frame every second */ - c->gop_size = frame_rate; + /* resolution must be a multiple of two */ + c->width = width; + c->height = height; + /* time base: this is the fundamental unit of time (in seconds) in terms + of which frame timestamps are represented. for fixed-fps content, + timebase should be 1/framerate and timestamp increments should be + identically 1. */ + c->time_base.den = frame_rate; + c->time_base.num = 1; + + Debug( 1, "Will encode in %d fps.", c->time_base.den ); + + /* emit one intra frame every second */ + c->gop_size = frame_rate; - // some formats want stream headers to be separate - if ( of->flags & AVFMT_GLOBALHEADER ) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; - } - else - { - Fatal( "of->video_codec == AV_CODEC_ID_NONE" ); - } + // some formats want stream headers to be separate + if ( of->flags & AVFMT_GLOBALHEADER ) + c->flags |= CODEC_FLAG_GLOBAL_HEADER; + } + else + { + Fatal( "of->video_codec == AV_CODEC_ID_NONE" ); + } } void VideoStream::SetParameters( ) @@ -278,512 +278,512 @@ void VideoStream::SetParameters( ) const char *VideoStream::MimeType( ) const { - for ( unsigned int i = 0; i < sizeof (mime_data) / sizeof (*mime_data); i++ ) - { - if ( strcmp( format, mime_data[i].format ) == 0 ) - { - Debug( 1, "MimeType is \"%s\"", mime_data[i].mime_type ); - return ( mime_data[i].mime_type); - } - } - const char *mime_type = of->mime_type; - if ( !mime_type ) - { - std::string mime = "video/"; - mime = mime.append( format ); - mime_type = mime.c_str( ); - Warning( "Unable to determine mime type for '%s' format, using '%s' as default", format, mime_type ); - } + for ( unsigned int i = 0; i < sizeof (mime_data) / sizeof (*mime_data); i++ ) + { + if ( strcmp( format, mime_data[i].format ) == 0 ) + { + Debug( 1, "MimeType is \"%s\"", mime_data[i].mime_type ); + return ( mime_data[i].mime_type); + } + } + const char *mime_type = of->mime_type; + if ( !mime_type ) + { + std::string mime = "video/"; + mime = mime.append( format ); + mime_type = mime.c_str( ); + Warning( "Unable to determine mime type for '%s' format, using '%s' as default", format, mime_type ); + } - Debug( 1, "MimeType is \"%s\"", mime_type ); + Debug( 1, "MimeType is \"%s\"", mime_type ); - return ( mime_type); + return ( mime_type); } void VideoStream::OpenStream( ) { - int avRet; + int avRet; - /* now that all the parameters are set, we can open the - video codecs and allocate the necessary encode buffers */ - if ( ost ) - { - AVCodecContext *c = ost->codec; - - /* open the codec */ + /* now that all the parameters are set, we can open the + video codecs and allocate the necessary encode buffers */ + if ( ost ) + { + AVCodecContext *c = ost->codec; + + /* open the codec */ #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) - if ( (avRet = avcodec_open( c, codec )) < 0 ) + if ( (avRet = avcodec_open( c, codec )) < 0 ) #else - if ( (avRet = avcodec_open2( c, codec, 0 )) < 0 ) + if ( (avRet = avcodec_open2( c, codec, 0 )) < 0 ) #endif - { - Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) ); - } + { + Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) ); + } - Debug( 1, "Opened codec" ); + Debug( 1, "Opened codec" ); - /* allocate the encoded raw picture */ + /* allocate the encoded raw picture */ #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - opicture = av_frame_alloc( ); + opicture = av_frame_alloc( ); #else - opicture = avcodec_alloc_frame( ); + opicture = avcodec_alloc_frame( ); #endif - if ( !opicture ) - { - Panic( "Could not allocate opicture" ); - } - - int size = avpicture_get_size( c->pix_fmt, c->width, c->height ); - uint8_t *opicture_buf = (uint8_t *)av_malloc( size ); - if ( !opicture_buf ) - { + if ( !opicture ) + { + Panic( "Could not allocate opicture" ); + } + + int size = avpicture_get_size( c->pix_fmt, c->width, c->height ); + uint8_t *opicture_buf = (uint8_t *)av_malloc( size ); + if ( !opicture_buf ) + { #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &opicture ); + av_frame_free( &opicture ); #else - av_freep( &opicture ); + av_freep( &opicture ); #endif - Panic( "Could not allocate opicture_buf" ); - } - avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height ); + Panic( "Could not allocate opicture_buf" ); + } + avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height ); - /* if the output format is not identical to the input format, then a temporary - picture is needed too. It is then converted to the required - output format */ - tmp_opicture = NULL; - if ( c->pix_fmt != pf ) - { + /* if the output format is not identical to the input format, then a temporary + picture is needed too. It is then converted to the required + output format */ + tmp_opicture = NULL; + if ( c->pix_fmt != pf ) + { #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - tmp_opicture = av_frame_alloc( ); + tmp_opicture = av_frame_alloc( ); #else - tmp_opicture = avcodec_alloc_frame( ); + tmp_opicture = avcodec_alloc_frame( ); #endif - if ( !tmp_opicture ) - { - Panic( "Could not allocate tmp_opicture" ); - } - int size = avpicture_get_size( pf, c->width, c->height ); - uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size ); - if ( !tmp_opicture_buf ) - { + if ( !tmp_opicture ) + { + Panic( "Could not allocate tmp_opicture" ); + } + int size = avpicture_get_size( pf, c->width, c->height ); + uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size ); + if ( !tmp_opicture_buf ) + { #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &tmp_opicture ); + av_frame_free( &tmp_opicture ); #else - av_freep( &tmp_opicture ); + av_freep( &tmp_opicture ); #endif - Panic( "Could not allocate tmp_opicture_buf" ); - } - avpicture_fill( (AVPicture *)tmp_opicture, tmp_opicture_buf, pf, c->width, c->height ); - } - } + Panic( "Could not allocate tmp_opicture_buf" ); + } + avpicture_fill( (AVPicture *)tmp_opicture, tmp_opicture_buf, pf, c->width, c->height ); + } + } - /* open the output file, if needed */ - if ( !(of->flags & AVFMT_NOFILE) ) - { - int ret; + /* open the output file, if needed */ + if ( !(of->flags & AVFMT_NOFILE) ) + { + int ret; #if LIBAVFORMAT_VERSION_CHECK(53, 15, 0, 21, 0) - ret = avio_open2( &ofc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL ); + ret = avio_open2( &ofc->pb, filename, AVIO_FLAG_WRITE, NULL, NULL ); #elif LIBAVFORMAT_VERSION_CHECK(52, 102, 0, 102, 0) - ret = avio_open( &ofc->pb, filename, AVIO_FLAG_WRITE ); + ret = avio_open( &ofc->pb, filename, AVIO_FLAG_WRITE ); #else - ret = url_fopen( &ofc->pb, filename, AVIO_FLAG_WRITE ); + ret = url_fopen( &ofc->pb, filename, AVIO_FLAG_WRITE ); #endif - if ( ret < 0 ) - { - Fatal( "Could not open '%s'", filename ); - } + if ( ret < 0 ) + { + Fatal( "Could not open '%s'", filename ); + } - Debug( 1, "Opened output \"%s\"", filename ); - } - else - { - Fatal( "of->flags & AVFMT_NOFILE" ); - } + Debug( 1, "Opened output \"%s\"", filename ); + } + else + { + Fatal( "of->flags & AVFMT_NOFILE" ); + } - video_outbuf = NULL; - if ( !(of->flags & AVFMT_RAWPICTURE) ) - { - /* allocate output buffer */ - /* XXX: API change will be done */ - // TODO: Make buffer dynamic. - video_outbuf_size = 4000000; - video_outbuf = (uint8_t *)malloc( video_outbuf_size ); - if ( video_outbuf == NULL ) { - Fatal("Unable to malloc memory for outbuf"); - } - } + video_outbuf = NULL; + if ( !(of->flags & AVFMT_RAWPICTURE) ) + { + /* allocate output buffer */ + /* XXX: API change will be done */ + // TODO: Make buffer dynamic. + video_outbuf_size = 4000000; + video_outbuf = (uint8_t *)malloc( video_outbuf_size ); + if ( video_outbuf == NULL ) { + Fatal("Unable to malloc memory for outbuf"); + } + } #if LIBAVFORMAT_VERSION_CHECK(52, 101, 0, 101, 0) - av_dump_format(ofc, 0, filename, 1); + av_dump_format(ofc, 0, filename, 1); #else - dump_format(ofc, 0, filename, 1); + dump_format(ofc, 0, filename, 1); #endif #if !LIBAVFORMAT_VERSION_CHECK(53, 2, 0, 4, 0) - int ret = av_write_header( ofc ); + int ret = av_write_header( ofc ); #else - int ret = avformat_write_header( ofc, NULL ); + int ret = avformat_write_header( ofc, NULL ); #endif - if ( ret < 0 ) - { - Fatal( "?_write_header failed with error %d \"%s\"", ret, av_err2str( ret ) ); - } + if ( ret < 0 ) + { + Fatal( "?_write_header failed with error %d \"%s\"", ret, av_err2str( ret ) ); + } } VideoStream::VideoStream( const char *in_filename, const char *in_format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ) : - filename(in_filename), - format(in_format), - last_pts( -1 ), - streaming_thread(0), - do_streaming(true), - buffer_copy(NULL), - buffer_copy_lock(new pthread_mutex_t), - buffer_copy_size(0), - buffer_copy_used(0), - packet_index(0) + filename(in_filename), + format(in_format), + last_pts( -1 ), + streaming_thread(0), + do_streaming(true), + buffer_copy(NULL), + buffer_copy_lock(new pthread_mutex_t), + buffer_copy_size(0), + buffer_copy_used(0), + packet_index(0) { - if ( !initialised ) - { - Initialise( ); - } - - if ( format ) - { - int length = strlen(format); - codec_and_format = new char[length+1];; - strcpy( codec_and_format, format ); - format = codec_and_format; - codec_name = NULL; - char *f = strchr(codec_and_format, '/'); - if (f != NULL) - { - *f = 0; - codec_name = f+1; - } - } + if ( !initialised ) + { + Initialise( ); + } + + if ( format ) + { + int length = strlen(format); + codec_and_format = new char[length+1];; + strcpy( codec_and_format, format ); + format = codec_and_format; + codec_name = NULL; + char *f = strchr(codec_and_format, '/'); + if (f != NULL) + { + *f = 0; + codec_name = f+1; + } + } - SetupFormat( ); - SetupCodec( colours, subpixelorder, width, height, bitrate, frame_rate ); - SetParameters( ); - - // Allocate buffered packets. - packet_buffers = new AVPacket*[2]; - packet_buffers[0] = new AVPacket(); - packet_buffers[1] = new AVPacket(); - packet_index = 0; - - // Initialize mutex used by streaming thread. - if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) - { - Fatal("pthread_mutex_init failed"); - } + SetupFormat( ); + SetupCodec( colours, subpixelorder, width, height, bitrate, frame_rate ); + SetParameters( ); + + // Allocate buffered packets. + packet_buffers = new AVPacket*[2]; + packet_buffers[0] = new AVPacket(); + packet_buffers[1] = new AVPacket(); + packet_index = 0; + + // Initialize mutex used by streaming thread. + if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) + { + Fatal("pthread_mutex_init failed"); + } } VideoStream::~VideoStream( ) { - Debug( 1, "VideoStream destructor." ); - - // Stop streaming thread. - if ( streaming_thread ) - { - do_streaming = false; - void* thread_exit_code; - - Debug( 1, "Asking streaming thread to exit." ); - - // Wait for thread to exit. - pthread_join(streaming_thread, &thread_exit_code); - } - - if ( buffer_copy != NULL ) - { - av_free( buffer_copy ); - } + Debug( 1, "VideoStream destructor." ); + + // Stop streaming thread. + if ( streaming_thread ) + { + do_streaming = false; + void* thread_exit_code; - if ( buffer_copy_lock ) - { - if ( pthread_mutex_destroy( buffer_copy_lock ) != 0 ) - { - Error( "pthread_mutex_destroy failed" ); - } - delete buffer_copy_lock; - } + Debug( 1, "Asking streaming thread to exit." ); - if (packet_buffers) { - delete packet_buffers[0]; - delete packet_buffers[1]; - delete[] packet_buffers; + // Wait for thread to exit. + pthread_join(streaming_thread, &thread_exit_code); + } + + if ( buffer_copy != NULL ) + { + av_free( buffer_copy ); + } + + if ( buffer_copy_lock ) + { + if ( pthread_mutex_destroy( buffer_copy_lock ) != 0 ) + { + Error( "pthread_mutex_destroy failed" ); } - - /* close each codec */ - if ( ost ) - { - avcodec_close( ost->codec ); - av_free( opicture->data[0] ); + delete buffer_copy_lock; + } + + if (packet_buffers) { + delete packet_buffers[0]; + delete packet_buffers[1]; + delete[] packet_buffers; + } + + /* close each codec */ + if ( ost ) + { + avcodec_close( ost->codec ); + av_free( opicture->data[0] ); #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &opicture ); + av_frame_free( &opicture ); #else - av_freep( &opicture ); + av_freep( &opicture ); #endif - if ( tmp_opicture ) - { - av_free( tmp_opicture->data[0] ); + if ( tmp_opicture ) + { + av_free( tmp_opicture->data[0] ); #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &tmp_opicture ); + av_frame_free( &tmp_opicture ); #else - av_freep( &tmp_opicture ); + av_freep( &tmp_opicture ); #endif - } - av_free( video_outbuf ); - } + } + av_free( video_outbuf ); + } - /* write the trailer, if any */ - av_write_trailer( ofc ); + /* write the trailer, if any */ + av_write_trailer( ofc ); - /* free the streams */ - for ( unsigned int i = 0; i < ofc->nb_streams; i++ ) - { - av_freep( &ofc->streams[i] ); - } + /* free the streams */ + for ( unsigned int i = 0; i < ofc->nb_streams; i++ ) + { + av_freep( &ofc->streams[i] ); + } - if ( !(of->flags & AVFMT_NOFILE) ) - { - /* close the output file */ + if ( !(of->flags & AVFMT_NOFILE) ) + { + /* close the output file */ #if LIBAVFORMAT_VERSION_CHECK(52, 105, 0, 105, 0) - avio_close( ofc->pb ); + avio_close( ofc->pb ); #else - url_fclose( ofc->pb ); + url_fclose( ofc->pb ); #endif - } + } - /* free the stream */ - av_free( ofc ); - - /* free format and codec_name data. */ - if ( codec_and_format ) - { - delete codec_and_format; - } + /* free the stream */ + av_free( ofc ); + + /* free format and codec_name data. */ + if ( codec_and_format ) + { + delete codec_and_format; + } } double VideoStream::EncodeFrame( const uint8_t *buffer, int buffer_size, bool _add_timestamp, unsigned int _timestamp ) { - if ( pthread_mutex_lock( buffer_copy_lock ) != 0 ) - { - Fatal( "EncodeFrame: pthread_mutex_lock failed." ); - } - - if (buffer_copy_size < buffer_size) - { - if ( buffer_copy ) - { - av_free( buffer_copy ); - } - - // Allocate a buffer to store source images for the streaming thread to encode. - buffer_copy = (uint8_t *)av_malloc( buffer_size ); - if ( !buffer_copy ) - { - Panic( "Could not allocate buffer_copy" ); - } - buffer_copy_size = buffer_size; - } - - add_timestamp = _add_timestamp; - timestamp = _timestamp; - buffer_copy_used = buffer_size; - memcpy(buffer_copy, buffer, buffer_size); - - if ( pthread_mutex_unlock( buffer_copy_lock ) != 0 ) - { - Fatal( "EncodeFrame: pthread_mutex_unlock failed." ); - } - - if ( streaming_thread == 0 ) - { - Debug( 1, "Starting streaming thread" ); - - // Start a thread for streaming encoded video. - if (pthread_create( &streaming_thread, NULL, StreamingThreadCallback, (void*) this) != 0){ - // Log a fatal error and exit the process. - Fatal( "VideoStream failed to create streaming thread." ); - } - } - - //return ActuallyEncodeFrame( buffer, buffer_size, add_timestamp, timestamp); - - return _timestamp; + if ( pthread_mutex_lock( buffer_copy_lock ) != 0 ) + { + Fatal( "EncodeFrame: pthread_mutex_lock failed." ); + } + + if (buffer_copy_size < buffer_size) + { + if ( buffer_copy ) + { + av_free( buffer_copy ); + } + + // Allocate a buffer to store source images for the streaming thread to encode. + buffer_copy = (uint8_t *)av_malloc( buffer_size ); + if ( !buffer_copy ) + { + Panic( "Could not allocate buffer_copy" ); + } + buffer_copy_size = buffer_size; + } + + add_timestamp = _add_timestamp; + timestamp = _timestamp; + buffer_copy_used = buffer_size; + memcpy(buffer_copy, buffer, buffer_size); + + if ( pthread_mutex_unlock( buffer_copy_lock ) != 0 ) + { + Fatal( "EncodeFrame: pthread_mutex_unlock failed." ); + } + + if ( streaming_thread == 0 ) + { + Debug( 1, "Starting streaming thread" ); + + // Start a thread for streaming encoded video. + if (pthread_create( &streaming_thread, NULL, StreamingThreadCallback, (void*) this) != 0){ + // Log a fatal error and exit the process. + Fatal( "VideoStream failed to create streaming thread." ); + } + } + + //return ActuallyEncodeFrame( buffer, buffer_size, add_timestamp, timestamp); + + return _timestamp; } double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp, unsigned int timestamp ) { #ifdef HAVE_LIBSWSCALE - static struct SwsContext *img_convert_ctx = 0; + static struct SwsContext *img_convert_ctx = 0; #endif // HAVE_LIBSWSCALE - AVCodecContext *c = ost->codec; + AVCodecContext *c = ost->codec; - if ( c->pix_fmt != pf ) - { - memcpy( tmp_opicture->data[0], buffer, buffer_size ); + if ( c->pix_fmt != pf ) + { + memcpy( tmp_opicture->data[0], buffer, buffer_size ); #ifdef HAVE_LIBSWSCALE - if ( !img_convert_ctx ) - { - img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL ); - if ( !img_convert_ctx ) - Panic( "Unable to initialise image scaling context" ); - } - sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize ); + if ( !img_convert_ctx ) + { + img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL ); + if ( !img_convert_ctx ) + Panic( "Unable to initialise image scaling context" ); + } + sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize ); #else // HAVE_LIBSWSCALE - Fatal( "swscale is required for MPEG mode" ); + Fatal( "swscale is required for MPEG mode" ); #endif // HAVE_LIBSWSCALE - } - else - { - memcpy( opicture->data[0], buffer, buffer_size ); - } - AVFrame *opicture_ptr = opicture; - - AVPacket *pkt = packet_buffers[packet_index]; - av_init_packet( pkt ); - int got_packet = 0; - if ( of->flags & AVFMT_RAWPICTURE ) - { + } + else + { + memcpy( opicture->data[0], buffer, buffer_size ); + } + AVFrame *opicture_ptr = opicture; + + AVPacket *pkt = packet_buffers[packet_index]; + av_init_packet( pkt ); + int got_packet = 0; + if ( of->flags & AVFMT_RAWPICTURE ) + { #if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2) - pkt->flags |= AV_PKT_FLAG_KEY; + pkt->flags |= AV_PKT_FLAG_KEY; #else - pkt->flags |= PKT_FLAG_KEY; + pkt->flags |= PKT_FLAG_KEY; #endif - pkt->stream_index = ost->index; - pkt->data = (uint8_t *)opicture_ptr; - pkt->size = sizeof (AVPicture); - got_packet = 1; - } - else - { - opicture_ptr->pts = c->frame_number; - opicture_ptr->quality = c->global_quality; + pkt->stream_index = ost->index; + pkt->data = (uint8_t *)opicture_ptr; + pkt->size = sizeof (AVPicture); + got_packet = 1; + } + else + { + opicture_ptr->pts = c->frame_number; + opicture_ptr->quality = c->global_quality; #if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100) - int ret = avcodec_encode_video2( c, pkt, opicture_ptr, &got_packet ); - if ( ret != 0 ) - { - Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) ); - } + int ret = avcodec_encode_video2( c, pkt, opicture_ptr, &got_packet ); + if ( ret != 0 ) + { + Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) ); + } #else - int out_size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, opicture_ptr ); - got_packet = out_size > 0 ? 1 : 0; - pkt->data = got_packet ? video_outbuf : NULL; - pkt->size = got_packet ? out_size : 0; + int out_size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, opicture_ptr ); + got_packet = out_size > 0 ? 1 : 0; + pkt->data = got_packet ? video_outbuf : NULL; + pkt->size = got_packet ? out_size : 0; #endif - if ( got_packet ) - { - if ( c->coded_frame->key_frame ) - { + if ( got_packet ) + { + if ( c->coded_frame->key_frame ) + { #if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2) - pkt->flags |= AV_PKT_FLAG_KEY; + pkt->flags |= AV_PKT_FLAG_KEY; #else - pkt->flags |= PKT_FLAG_KEY; + pkt->flags |= PKT_FLAG_KEY; #endif - } + } - if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) - { - pkt->pts = av_rescale_q( pkt->pts, c->time_base, ost->time_base ); - } - if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) - { - pkt->dts = av_rescale_q( pkt->dts, c->time_base, ost->time_base ); - } - pkt->duration = av_rescale_q( pkt->duration, c->time_base, ost->time_base ); - pkt->stream_index = ost->index; - } - } - - return ( opicture_ptr->pts); + if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) + { + pkt->pts = av_rescale_q( pkt->pts, c->time_base, ost->time_base ); + } + if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) + { + pkt->dts = av_rescale_q( pkt->dts, c->time_base, ost->time_base ); + } + pkt->duration = av_rescale_q( pkt->duration, c->time_base, ost->time_base ); + pkt->stream_index = ost->index; + } + } + + return ( opicture_ptr->pts); } int VideoStream::SendPacket(AVPacket *packet) { - - int ret = av_write_frame( ofc, packet ); - if ( ret != 0 ) - { - Fatal( "Error %d while writing video frame: %s", ret, av_err2str( errno ) ); - } + + int ret = av_write_frame( ofc, packet ); + if ( ret != 0 ) + { + Fatal( "Error %d while writing video frame: %s", ret, av_err2str( errno ) ); + } #if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) - av_packet_unref( packet ); + av_packet_unref( packet ); #else - av_free_packet( packet ); + av_free_packet( packet ); #endif - return ret; + return ret; } void *VideoStream::StreamingThreadCallback(void *ctx){ - - Debug( 1, "StreamingThreadCallback started" ); - - if (ctx == NULL) return NULL; + + Debug( 1, "StreamingThreadCallback started" ); + + if (ctx == NULL) return NULL; - VideoStream* videoStream = reinterpret_cast(ctx); - - const uint64_t nanosecond_multiplier = 1000000000; - - uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) ); - uint64_t frame_count = 0; - timespec start_time; - clock_gettime(CLOCK_MONOTONIC, &start_time); - uint64_t start_time_ns = (start_time.tv_sec*nanosecond_multiplier) + start_time.tv_nsec; - while(videoStream->do_streaming) - { - timespec current_time; - clock_gettime(CLOCK_MONOTONIC, ¤t_time); - uint64_t current_time_ns = (current_time.tv_sec*nanosecond_multiplier) + current_time.tv_nsec; - uint64_t target_ns = start_time_ns + (target_interval_ns * frame_count); - - if ( current_time_ns < target_ns ) - { - // It's not time to render a frame yet. - usleep( (target_ns - current_time_ns) * 0.001 ); - } - - // By sending the last rendered frame we deliver frames to the client more accurate. - // If we're encoding the frame before sending it there will be lag. - // Since this lag is not constant the client may skip frames. - - // Get the last rendered packet. - AVPacket *packet = videoStream->packet_buffers[videoStream->packet_index]; - if (packet->size) { - videoStream->SendPacket(packet); - } + VideoStream* videoStream = reinterpret_cast(ctx); + + const uint64_t nanosecond_multiplier = 1000000000; + + uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) ); + uint64_t frame_count = 0; + timespec start_time; + clock_gettime(CLOCK_MONOTONIC, &start_time); + uint64_t start_time_ns = (start_time.tv_sec*nanosecond_multiplier) + start_time.tv_nsec; + while(videoStream->do_streaming) + { + timespec current_time; + clock_gettime(CLOCK_MONOTONIC, ¤t_time); + uint64_t current_time_ns = (current_time.tv_sec*nanosecond_multiplier) + current_time.tv_nsec; + uint64_t target_ns = start_time_ns + (target_interval_ns * frame_count); + + if ( current_time_ns < target_ns ) + { + // It's not time to render a frame yet. + usleep( (target_ns - current_time_ns) * 0.001 ); + } + + // By sending the last rendered frame we deliver frames to the client more accurate. + // If we're encoding the frame before sending it there will be lag. + // Since this lag is not constant the client may skip frames. + + // Get the last rendered packet. + AVPacket *packet = videoStream->packet_buffers[videoStream->packet_index]; + if (packet->size) { + videoStream->SendPacket(packet); + } #if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) - av_packet_unref( packet); + av_packet_unref( packet); #else - av_free_packet( packet ); + av_free_packet( packet ); #endif - videoStream->packet_index = videoStream->packet_index ? 0 : 1; - - // Lock buffer and render next frame. - - if ( pthread_mutex_lock( videoStream->buffer_copy_lock ) != 0 ) - { - Fatal( "StreamingThreadCallback: pthread_mutex_lock failed." ); - } - - if ( videoStream->buffer_copy ) - { - // Encode next frame. - videoStream->ActuallyEncodeFrame( videoStream->buffer_copy, videoStream->buffer_copy_used, videoStream->add_timestamp, videoStream->timestamp ); - } - - if ( pthread_mutex_unlock( videoStream->buffer_copy_lock ) != 0 ) - { - Fatal( "StreamingThreadCallback: pthread_mutex_unlock failed." ); - } - - frame_count++; - } - - return 0; + videoStream->packet_index = videoStream->packet_index ? 0 : 1; + + // Lock buffer and render next frame. + + if ( pthread_mutex_lock( videoStream->buffer_copy_lock ) != 0 ) + { + Fatal( "StreamingThreadCallback: pthread_mutex_lock failed." ); + } + + if ( videoStream->buffer_copy ) + { + // Encode next frame. + videoStream->ActuallyEncodeFrame( videoStream->buffer_copy, videoStream->buffer_copy_used, videoStream->add_timestamp, videoStream->timestamp ); + } + + if ( pthread_mutex_unlock( videoStream->buffer_copy_lock ) != 0 ) + { + Fatal( "StreamingThreadCallback: pthread_mutex_unlock failed." ); + } + + frame_count++; + } + + return 0; } #endif // HAVE_LIBAVCODEC diff --git a/src/zm_mpeg.h b/src/zm_mpeg.h index b54776e70..e2ec33592 100644 --- a/src/zm_mpeg.h +++ b/src/zm_mpeg.h @@ -27,60 +27,60 @@ class VideoStream { protected: - struct MimeData - { - const char *format; - const char *mime_type; - }; + struct MimeData + { + const char *format; + const char *mime_type; + }; protected: - static bool initialised; - static struct MimeData mime_data[]; + static bool initialised; + static struct MimeData mime_data[]; protected: - char *codec_and_format; - const char *filename; - const char *format; - const char *codec_name; - enum _AVPIXELFORMAT pf; - AVOutputFormat *of; - AVFormatContext *ofc; - AVStream *ost; - AVCodec *codec; - AVFrame *opicture; - AVFrame *tmp_opicture; - uint8_t *video_outbuf; - int video_outbuf_size; - double last_pts; - - pthread_t streaming_thread; - bool do_streaming; - uint8_t *buffer_copy; - bool add_timestamp; - unsigned int timestamp; - pthread_mutex_t *buffer_copy_lock; - int buffer_copy_size; - int buffer_copy_used; - AVPacket** packet_buffers; - int packet_index; - int SendPacket(AVPacket *packet); - static void* StreamingThreadCallback(void *ctx); + char *codec_and_format; + const char *filename; + const char *format; + const char *codec_name; + enum _AVPIXELFORMAT pf; + AVOutputFormat *of; + AVFormatContext *ofc; + AVStream *ost; + AVCodec *codec; + AVFrame *opicture; + AVFrame *tmp_opicture; + uint8_t *video_outbuf; + int video_outbuf_size; + double last_pts; + + pthread_t streaming_thread; + bool do_streaming; + uint8_t *buffer_copy; + bool add_timestamp; + unsigned int timestamp; + pthread_mutex_t *buffer_copy_lock; + int buffer_copy_size; + int buffer_copy_used; + AVPacket** packet_buffers; + int packet_index; + int SendPacket(AVPacket *packet); + static void* StreamingThreadCallback(void *ctx); protected: - static void Initialise(); + static void Initialise(); - void SetupFormat( ); - void SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ); - void SetParameters(); - void ActuallyOpenStream(); - double ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp=false, unsigned int timestamp=0 ); + void SetupFormat( ); + void SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ); + void SetParameters(); + void ActuallyOpenStream(); + double ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp=false, unsigned int timestamp=0 ); public: - VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ); - ~VideoStream(); - const char *MimeType() const; - void OpenStream(); - double EncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp=false, unsigned int timestamp=0 ); + VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ); + ~VideoStream(); + const char *MimeType() const; + void OpenStream(); + double EncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp=false, unsigned int timestamp=0 ); }; #endif // HAVE_LIBAVCODEC diff --git a/src/zm_poly.cpp b/src/zm_poly.cpp index 4eee73f46..cddcced46 100644 --- a/src/zm_poly.cpp +++ b/src/zm_poly.cpp @@ -28,95 +28,95 @@ void Polygon::calcArea() { - double float_area = 0.0L; - for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) - { - double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L; - float_area += trap_area; - //printf( "%.2f (%.2f)\n", float_area, trap_area ); - } - area = (int)round(fabs(float_area)); + double float_area = 0.0L; + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) + { + double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L; + float_area += trap_area; + //printf( "%.2f (%.2f)\n", float_area, trap_area ); + } + area = (int)round(fabs(float_area)); } void Polygon::calcCentre() { - if ( !area && n_coords ) - calcArea(); - double float_x = 0.0L, float_y = 0.0L; - for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) - { - float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2))); - float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2))); - } - float_x /= (6*area); - float_y /= (6*area); - //printf( "%.2f,%.2f\n", float_x, float_y ); - centre = Coord( (int)round(float_x), (int)round(float_y) ); + if ( !area && n_coords ) + calcArea(); + double float_x = 0.0L, float_y = 0.0L; + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) + { + float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2))); + float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2))); + } + float_x /= (6*area); + float_y /= (6*area); + //printf( "%.2f,%.2f\n", float_x, float_y ); + centre = Coord( (int)round(float_x), (int)round(float_y) ); } Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords ) { - coords = new Coord[n_coords]; + coords = new Coord[n_coords]; - int min_x = -1; - int max_x = -1; - int min_y = -1; - int max_y = -1; - for( int i = 0; i < n_coords; i++ ) - { - coords[i] = p_coords[i]; - if ( min_x == -1 || coords[i].X() < min_x ) - min_x = coords[i].X(); - if ( max_x == -1 || coords[i].X() > max_x ) - max_x = coords[i].X(); - if ( min_y == -1 || coords[i].Y() < min_y ) - min_y = coords[i].Y(); - if ( max_y == -1 || coords[i].Y() > max_y ) - max_y = coords[i].Y(); - } - extent = Box( min_x, min_y, max_x, max_y ); - calcArea(); - calcCentre(); + int min_x = -1; + int max_x = -1; + int min_y = -1; + int max_y = -1; + for( int i = 0; i < n_coords; i++ ) + { + coords[i] = p_coords[i]; + if ( min_x == -1 || coords[i].X() < min_x ) + min_x = coords[i].X(); + if ( max_x == -1 || coords[i].X() > max_x ) + max_x = coords[i].X(); + if ( min_y == -1 || coords[i].Y() < min_y ) + min_y = coords[i].Y(); + if ( max_y == -1 || coords[i].Y() > max_y ) + max_y = coords[i].Y(); + } + extent = Box( min_x, min_y, max_x, max_y ); + calcArea(); + calcCentre(); } Polygon::Polygon( const Polygon &p_polygon ) : n_coords( p_polygon.n_coords ), extent( p_polygon.extent ), area( p_polygon.area ), centre( p_polygon.centre ) { - coords = new Coord[n_coords]; - for( int i = 0; i < n_coords; i++ ) - { - coords[i] = p_polygon.coords[i]; - } + coords = new Coord[n_coords]; + for( int i = 0; i < n_coords; i++ ) + { + coords[i] = p_polygon.coords[i]; + } } Polygon &Polygon::operator=( const Polygon &p_polygon ) { - if ( n_coords < p_polygon.n_coords ) - { - delete[] coords; - coords = new Coord[p_polygon.n_coords]; - } - n_coords = p_polygon.n_coords; - for( int i = 0; i < n_coords; i++ ) - { - coords[i] = p_polygon.coords[i]; - } - extent = p_polygon.extent; - area = p_polygon.area; - centre = p_polygon.centre; - return( *this ); + if ( n_coords < p_polygon.n_coords ) + { + delete[] coords; + coords = new Coord[p_polygon.n_coords]; + } + n_coords = p_polygon.n_coords; + for( int i = 0; i < n_coords; i++ ) + { + coords[i] = p_polygon.coords[i]; + } + extent = p_polygon.extent; + area = p_polygon.area; + centre = p_polygon.centre; + return( *this ); } bool Polygon::isInside( const Coord &coord ) const { - bool inside = false; - for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) - { - if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) ) - || ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y()))) - && (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X())) - { - inside = !inside; - } - } - return( inside ); + bool inside = false; + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) + { + if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) ) + || ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y()))) + && (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X())) + { + inside = !inside; + } + } + return( inside ); } diff --git a/src/zm_poly.h b/src/zm_poly.h index 854a3c322..7ba3043fd 100644 --- a/src/zm_poly.h +++ b/src/zm_poly.h @@ -33,93 +33,93 @@ class Polygon { protected: - struct Edge - { - int min_y; - int max_y; - double min_x; - double _1_m; + struct Edge + { + int min_y; + int max_y; + double min_x; + double _1_m; - static int CompareYX( const void *p1, const void *p2 ) - { - const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; - if ( e1->min_y == e2->min_y ) - return( int(e1->min_x - e2->min_x) ); - else - return( int(e1->min_y - e2->min_y) ); - } - static int CompareX( const void *p1, const void *p2 ) - { - const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; - return( int(e1->min_x - e2->min_x) ); - } - }; + static int CompareYX( const void *p1, const void *p2 ) + { + const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; + if ( e1->min_y == e2->min_y ) + return( int(e1->min_x - e2->min_x) ); + else + return( int(e1->min_y - e2->min_y) ); + } + static int CompareX( const void *p1, const void *p2 ) + { + const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; + return( int(e1->min_x - e2->min_x) ); + } + }; - struct Slice - { - int min_x; - int max_x; - int n_edges; - int *edges; + struct Slice + { + int min_x; + int max_x; + int n_edges; + int *edges; - Slice() - { - n_edges = 0; - edges = 0; - } - ~Slice() - { - delete edges; - } - }; + Slice() + { + n_edges = 0; + edges = 0; + } + ~Slice() + { + delete edges; + } + }; protected: - int n_coords; - Coord *coords; - Box extent; - int area; - Coord centre; - Edge *edges; - Slice *slices; + int n_coords; + Coord *coords; + Box extent; + int area; + Coord centre; + Edge *edges; + Slice *slices; protected: - void initialiseEdges(); - void calcArea(); - void calcCentre(); + void initialiseEdges(); + void calcArea(); + void calcCentre(); public: - inline Polygon() : n_coords( 0 ), coords( 0 ), area( 0 ) - { - } - Polygon( int p_n_coords, const Coord *p_coords ); - Polygon( const Polygon &p_polygon ); - ~Polygon() - { - delete[] coords; - } + inline Polygon() : n_coords( 0 ), coords( 0 ), area( 0 ) + { + } + Polygon( int p_n_coords, const Coord *p_coords ); + Polygon( const Polygon &p_polygon ); + ~Polygon() + { + delete[] coords; + } - Polygon &operator=( const Polygon &p_polygon ); + Polygon &operator=( const Polygon &p_polygon ); - inline int getNumCoords() const { return( n_coords ); } - inline const Coord &getCoord( int index ) const - { - return( coords[index] ); - } + inline int getNumCoords() const { return( n_coords ); } + inline const Coord &getCoord( int index ) const + { + return( coords[index] ); + } - inline const Box &Extent() const { return( extent ); } - inline int LoX() const { return( extent.LoX() ); } - inline int HiX() const { return( extent.HiX() ); } - inline int LoY() const { return( extent.LoY() ); } - inline int HiY() const { return( extent.HiY() ); } - inline int Width() const { return( extent.Width() ); } - inline int Height() const { return( extent.Height() ); } + inline const Box &Extent() const { return( extent ); } + inline int LoX() const { return( extent.LoX() ); } + inline int HiX() const { return( extent.HiX() ); } + inline int LoY() const { return( extent.LoY() ); } + inline int HiY() const { return( extent.HiY() ); } + inline int Width() const { return( extent.Width() ); } + inline int Height() const { return( extent.Height() ); } - inline int Area() const { return( area ); } - inline const Coord &Centre() const - { - return( centre ); - } - bool isInside( const Coord &coord ) const; + inline int Area() const { return( area ); } + inline const Coord &Centre() const + { + return( centre ); + } + bool isInside( const Coord &coord ) const; }; #endif // ZM_POLY_H diff --git a/src/zm_regexp.cpp b/src/zm_regexp.cpp index 43f738217..cfa686688 100644 --- a/src/zm_regexp.cpp +++ b/src/zm_regexp.cpp @@ -26,99 +26,99 @@ RegExpr::RegExpr( const char *pattern, int flags, int p_max_matches ) : max_matches( p_max_matches ), match_buffers( 0 ), match_lengths( 0 ), match_valid( 0 ) { - const char *errstr; - int erroffset = 0; - if ( !(regex = pcre_compile( pattern, flags, &errstr, &erroffset, 0 )) ) - { - Panic( "pcre_compile(%s): %s at %d", pattern, errstr, erroffset ); - } + const char *errstr; + int erroffset = 0; + if ( !(regex = pcre_compile( pattern, flags, &errstr, &erroffset, 0 )) ) + { + Panic( "pcre_compile(%s): %s at %d", pattern, errstr, erroffset ); + } - regextra = pcre_study( regex, 0, &errstr ); - if ( errstr ) - { - Panic( "pcre_study(%s): %s", pattern, errstr ); - } + regextra = pcre_study( regex, 0, &errstr ); + if ( errstr ) + { + Panic( "pcre_study(%s): %s", pattern, errstr ); + } - if ( (ok = (bool)regex) ) - { - match_vectors = new int[3*max_matches]; - memset( match_vectors, 0, sizeof(*match_vectors)*3*max_matches ); - match_buffers = new char *[max_matches]; - memset( match_buffers, 0, sizeof(*match_buffers)*max_matches ); - match_lengths = new int[max_matches]; - memset( match_lengths, 0, sizeof(*match_lengths)*max_matches ); - match_valid = new bool[max_matches]; - memset( match_valid, 0, sizeof(*match_valid)*max_matches ); - } - n_matches = 0; + if ( (ok = (bool)regex) ) + { + match_vectors = new int[3*max_matches]; + memset( match_vectors, 0, sizeof(*match_vectors)*3*max_matches ); + match_buffers = new char *[max_matches]; + memset( match_buffers, 0, sizeof(*match_buffers)*max_matches ); + match_lengths = new int[max_matches]; + memset( match_lengths, 0, sizeof(*match_lengths)*max_matches ); + match_valid = new bool[max_matches]; + memset( match_valid, 0, sizeof(*match_valid)*max_matches ); + } + n_matches = 0; } RegExpr::~RegExpr() { - for ( int i = 0; i < max_matches; i++ ) - { - if ( match_buffers[i] ) - { - delete[] match_buffers[i]; - } - } - delete[] match_valid; - delete[] match_lengths; - delete[] match_buffers; - delete[] match_vectors; + for ( int i = 0; i < max_matches; i++ ) + { + if ( match_buffers[i] ) + { + delete[] match_buffers[i]; + } + } + delete[] match_valid; + delete[] match_lengths; + delete[] match_buffers; + delete[] match_vectors; } int RegExpr::Match( const char *subject_string, int subject_length, int flags ) { - match_string = subject_string; + match_string = subject_string; - n_matches = pcre_exec( regex, regextra, subject_string, subject_length, 0, flags, match_vectors, 2*max_matches ); + n_matches = pcre_exec( regex, regextra, subject_string, subject_length, 0, flags, match_vectors, 2*max_matches ); - if ( n_matches <= 0 ) - { - if ( n_matches < PCRE_ERROR_NOMATCH ) - { - Error( "Error %d executing regular expression", n_matches ); - } - return( n_matches = 0 ); - } + if ( n_matches <= 0 ) + { + if ( n_matches < PCRE_ERROR_NOMATCH ) + { + Error( "Error %d executing regular expression", n_matches ); + } + return( n_matches = 0 ); + } - for( int i = 0; i < max_matches; i++ ) - { - match_valid[i] = false; - } - return( n_matches ); + for( int i = 0; i < max_matches; i++ ) + { + match_valid[i] = false; + } + return( n_matches ); } const char *RegExpr::MatchString( int match_index ) const { - if ( match_index > n_matches ) - { - return( 0 ); - } - if ( !match_valid[match_index] ) - { - int match_len = match_vectors[(2*match_index)+1]-match_vectors[2*match_index]; - if ( match_lengths[match_index] < (match_len+1) ) - { - delete[] match_buffers[match_index]; - match_buffers[match_index] = new char[match_len+1]; - match_lengths[match_index] = match_len+1; - } - memcpy( match_buffers[match_index], match_string+match_vectors[2*match_index], match_len ); - match_buffers[match_index][match_len] = '\0'; - match_valid[match_index] = true; - } - return( match_buffers[match_index] ); + if ( match_index > n_matches ) + { + return( 0 ); + } + if ( !match_valid[match_index] ) + { + int match_len = match_vectors[(2*match_index)+1]-match_vectors[2*match_index]; + if ( match_lengths[match_index] < (match_len+1) ) + { + delete[] match_buffers[match_index]; + match_buffers[match_index] = new char[match_len+1]; + match_lengths[match_index] = match_len+1; + } + memcpy( match_buffers[match_index], match_string+match_vectors[2*match_index], match_len ); + match_buffers[match_index][match_len] = '\0'; + match_valid[match_index] = true; + } + return( match_buffers[match_index] ); } int RegExpr::MatchLength( int match_index ) const { - if ( match_index > n_matches ) - { - return( 0 ); - } - return( match_vectors[(2*match_index)+1]-match_vectors[2*match_index] ); + if ( match_index > n_matches ) + { + return( 0 ); + } + return( match_vectors[(2*match_index)+1]-match_vectors[2*match_index] ); } #endif // HAVE_LIBPCRE diff --git a/src/zm_regexp.h b/src/zm_regexp.h index f1c9d705d..1b1a9d518 100644 --- a/src/zm_regexp.h +++ b/src/zm_regexp.h @@ -35,29 +35,29 @@ class RegExpr { protected: - pcre *regex; - pcre_extra *regextra; - int max_matches; - int *match_vectors; - mutable char **match_buffers; - int *match_lengths; - bool *match_valid; + pcre *regex; + pcre_extra *regextra; + int max_matches; + int *match_vectors; + mutable char **match_buffers; + int *match_lengths; + bool *match_valid; protected: - const char *match_string; - int n_matches; - + const char *match_string; + int n_matches; + protected: - bool ok; + bool ok; public: - RegExpr( const char *pattern, int cflags=0, int p_max_matches=32 ); - ~RegExpr(); - bool Ok() const { return( ok ); } - int MatchCount() const { return( n_matches ); } - int Match( const char *subject_string, int subject_length, int flags=0 ); - const char *MatchString( int match_index ) const; - int MatchLength( int match_index ) const; + RegExpr( const char *pattern, int cflags=0, int p_max_matches=32 ); + ~RegExpr(); + bool Ok() const { return( ok ); } + int MatchCount() const { return( n_matches ); } + int Match( const char *subject_string, int subject_length, int flags=0 ); + const char *MatchString( int match_index ) const; + int MatchLength( int match_index ) const; }; #endif // HAVE_LIBPCRE diff --git a/src/zm_remote_camera.cpp b/src/zm_remote_camera.cpp index 8ac4a51ba..b82589cd6 100644 --- a/src/zm_remote_camera.cpp +++ b/src/zm_remote_camera.cpp @@ -22,66 +22,66 @@ #include "zm_utils.h" RemoteCamera::RemoteCamera( int p_id, const std::string &p_protocol, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), - protocol( p_protocol ), - host( p_host ), - port( p_port ), - path( p_path ), - hp( 0 ) + Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + protocol( p_protocol ), + host( p_host ), + port( p_port ), + path( p_path ), + hp( 0 ) { - if ( path[0] != '/' ) - path = '/'+path; + if ( path[0] != '/' ) + path = '/'+path; } RemoteCamera::~RemoteCamera() { - if(hp != NULL) { - freeaddrinfo(hp); - hp = NULL; - } + if(hp != NULL) { + freeaddrinfo(hp); + hp = NULL; + } } void RemoteCamera::Initialise() { - if( protocol.empty() ) - Fatal( "No protocol specified for remote camera" ); + if( protocol.empty() ) + Fatal( "No protocol specified for remote camera" ); - if( host.empty() ) - Fatal( "No host specified for remote camera" ); + if( host.empty() ) + Fatal( "No host specified for remote camera" ); - if( port.empty() ) - Fatal( "No port specified for remote camera" ); + if( port.empty() ) + Fatal( "No port specified for remote camera" ); - //if( path.empty() ) - //Fatal( "No path specified for remote camera" ); + //if( path.empty() ) + //Fatal( "No path specified for remote camera" ); - // Cache as much as we can to speed things up - std::string::size_type authIndex = host.rfind( '@' ); + // Cache as much as we can to speed things up + std::string::size_type authIndex = host.rfind( '@' ); - if ( authIndex != std::string::npos ) - { - auth = host.substr( 0, authIndex ); - host.erase( 0, authIndex+1 ); - auth64 = base64Encode( auth ); + if ( authIndex != std::string::npos ) + { + auth = host.substr( 0, authIndex ); + host.erase( 0, authIndex+1 ); + auth64 = base64Encode( auth ); - authIndex = auth.rfind( ':' ); - username = auth.substr(0,authIndex); - password = auth.substr( authIndex+1, auth.length() ); + authIndex = auth.rfind( ':' ); + username = auth.substr(0,authIndex); + password = auth.substr( authIndex+1, auth.length() ); - } + } - mNeedAuth = false; - mAuthenticator = new zm::Authenticator(username,password); + mNeedAuth = false; + mAuthenticator = new zm::Authenticator(username,password); - struct addrinfo hints; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; - int ret = getaddrinfo(host.c_str(), port.c_str(), &hints, &hp); - if ( ret != 0 ) - { - Fatal( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) ); - } + int ret = getaddrinfo(host.c_str(), port.c_str(), &hints, &hp); + if ( ret != 0 ) + { + Fatal( "Can't getaddrinfo(%s port %s): %s", host.c_str(), port.c_str(), gai_strerror(ret) ); + } } diff --git a/src/zm_remote_camera.h b/src/zm_remote_camera.h index 7e3ae79a8..647782fd1 100644 --- a/src/zm_remote_camera.h +++ b/src/zm_remote_camera.h @@ -35,44 +35,44 @@ class RemoteCamera : public Camera { protected: - std::string protocol; - std::string host; - std::string port; - std::string path; - std::string auth; - std::string username; - std::string password; - std::string auth64; + std::string protocol; + std::string host; + std::string port; + std::string path; + std::string auth; + std::string username; + std::string password; + std::string auth64; - // Reworked authentication system - // First try without authentication, even if we have a username and password - // on receiving a 401 response, select authentication method (basic or digest) - // fill required fields and set needAuth - // subsequent requests can set the required authentication header. - bool mNeedAuth; - zm::Authenticator* mAuthenticator; + // Reworked authentication system + // First try without authentication, even if we have a username and password + // on receiving a 401 response, select authentication method (basic or digest) + // fill required fields and set needAuth + // subsequent requests can set the required authentication header. + bool mNeedAuth; + zm::Authenticator* mAuthenticator; protected: - struct addrinfo *hp; + struct addrinfo *hp; public: - RemoteCamera( int p_id, const std::string &p_proto, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - virtual ~RemoteCamera(); + RemoteCamera( int p_id, const std::string &p_proto, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + virtual ~RemoteCamera(); - const std::string &Protocol() const { return( protocol ); } - const std::string &Host() const { return( host ); } - const std::string &Port() const { return( port ); } - const std::string &Path() const { return( path ); } - const std::string &Auth() const { return( auth ); } - const std::string &Username() const { return( username ); } - const std::string &Password() const { return( password ); } + const std::string &Protocol() const { return( protocol ); } + const std::string &Host() const { return( host ); } + const std::string &Port() const { return( port ); } + const std::string &Path() const { return( path ); } + const std::string &Auth() const { return( auth ); } + const std::string &Username() const { return( username ); } + const std::string &Password() const { return( password ); } - virtual void Initialise(); - virtual void Terminate() = 0; - virtual int Connect() = 0; - virtual int Disconnect() = 0; - virtual int PreCapture() = 0; - virtual int Capture( Image &image ) = 0; - virtual int PostCapture() = 0; + virtual void Initialise(); + virtual void Terminate() = 0; + virtual int Connect() = 0; + virtual int Disconnect() = 0; + virtual int PreCapture() = 0; + virtual int Capture( Image &image ) = 0; + virtual int PostCapture() = 0; }; #endif // ZM_REMOTE_CAMERA_H diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp index 006f80faf..9454b8d69 100644 --- a/src/zm_remote_camera_http.cpp +++ b/src/zm_remote_camera_http.cpp @@ -32,120 +32,120 @@ #endif RemoteCameraHttp::RemoteCameraHttp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - RemoteCamera( p_id, "http", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ) + RemoteCamera( p_id, "http", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ) { - sd = -1; + sd = -1; - timeout.tv_sec = 0; - timeout.tv_usec = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 0; - if ( p_method == "simple" ) - method = SIMPLE; - else if ( p_method == "regexp" ) - method = REGEXP; - else - Fatal( "Unrecognised method '%s' when creating HTTP camera %d", p_method.c_str(), id ); - if ( capture ) - { - Initialise(); - } + if ( p_method == "simple" ) + method = SIMPLE; + else if ( p_method == "regexp" ) + method = REGEXP; + else + Fatal( "Unrecognised method '%s' when creating HTTP camera %d", p_method.c_str(), id ); + if ( capture ) + { + Initialise(); + } } RemoteCameraHttp::~RemoteCameraHttp() { - if ( capture ) - { - Terminate(); - } + if ( capture ) + { + Terminate(); + } } void RemoteCameraHttp::Initialise() { - RemoteCamera::Initialise(); + RemoteCamera::Initialise(); - if ( request.empty() ) - { - request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); - request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); - request += stringtf( "Host: %s\r\n", host.c_str()); - if ( strcmp( config.http_version, "1.0" ) == 0 ) - request += stringtf( "Connection: Keep-Alive\r\n" ); - if ( !auth.empty() ) - request += stringtf( "Authorization: Basic %s\r\n", auth64.c_str() ); - request += "\r\n"; - Debug( 2, "Request: %s", request.c_str() ); - } + if ( request.empty() ) + { + request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); + request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); + request += stringtf( "Host: %s\r\n", host.c_str()); + if ( strcmp( config.http_version, "1.0" ) == 0 ) + request += stringtf( "Connection: Keep-Alive\r\n" ); + if ( !auth.empty() ) + request += stringtf( "Authorization: Basic %s\r\n", auth64.c_str() ); + request += "\r\n"; + Debug( 2, "Request: %s", request.c_str() ); + } - if ( !timeout.tv_sec ) - { - timeout.tv_sec = config.http_timeout/1000; - timeout.tv_usec = (config.http_timeout%1000)*1000; - } + if ( !timeout.tv_sec ) + { + timeout.tv_sec = config.http_timeout/1000; + timeout.tv_usec = (config.http_timeout%1000)*1000; + } - int max_size = width*height*colours; + int max_size = width*height*colours; - buffer.size( max_size ); + buffer.size( max_size ); - mode = SINGLE_IMAGE; - format = UNDEF; - state = HEADER; + mode = SINGLE_IMAGE; + format = UNDEF; + state = HEADER; } int RemoteCameraHttp::Connect() { - struct addrinfo *p; + struct addrinfo *p; - for(p = hp; p != NULL; p = p->ai_next) + for(p = hp; p != NULL; p = p->ai_next) + { + sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol ); + if ( sd < 0 ) { - sd = socket( p->ai_family, p->ai_socktype, p->ai_protocol ); - if ( sd < 0 ) - { - Warning("Can't create socket: %s", strerror(errno) ); - continue; - } - - if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) - { - close(sd); - sd = -1; - Warning("Can't connect to remote camera: %s", strerror(errno) ); - continue; - } - - /* If we got here, we must have connected successfully */ - break; + Warning("Can't create socket: %s", strerror(errno) ); + continue; } - if(p == NULL) { - Error("Unable to connect to the remote camera, aborting"); - return( -1 ); + if ( connect( sd, p->ai_addr, p->ai_addrlen ) < 0 ) + { + close(sd); + sd = -1; + Warning("Can't connect to remote camera: %s", strerror(errno) ); + continue; } - Debug( 3, "Connected to host, socket = %d", sd ); - return( sd ); + /* If we got here, we must have connected successfully */ + break; + } + + if(p == NULL) { + Error("Unable to connect to the remote camera, aborting"); + return( -1 ); + } + + Debug( 3, "Connected to host, socket = %d", sd ); + return( sd ); } int RemoteCameraHttp::Disconnect() { - close( sd ); - sd = -1; - Debug( 3, "Disconnected from host" ); - return( 0 ); + close( sd ); + sd = -1; + Debug( 3, "Disconnected from host" ); + return( 0 ); } int RemoteCameraHttp::SendRequest() { - Debug( 2, "Sending request: %s", request.c_str() ); - if ( write( sd, request.data(), request.length() ) < 0 ) - { - Error( "Can't write: %s", strerror(errno) ); - Disconnect(); - return( -1 ); - } - format = UNDEF; - state = HEADER; - Debug( 3, "Request sent" ); - return( 0 ); + Debug( 2, "Sending request: %s", request.c_str() ); + if ( write( sd, request.data(), request.length() ) < 0 ) + { + Error( "Can't write: %s", strerror(errno) ); + Disconnect(); + return( -1 ); + } + format = UNDEF; + state = HEADER; + Debug( 3, "Request sent" ); + return( 0 ); } /* Return codes are as follows: @@ -156,1037 +156,1037 @@ int RemoteCameraHttp::SendRequest() int RemoteCameraHttp::ReadData( Buffer &buffer, int bytes_expected ) { - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(sd, &rfds); + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(sd, &rfds); - struct timeval temp_timeout = timeout; + struct timeval temp_timeout = timeout; - int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout ); - if( n_found == 0 ) + int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout ); + if( n_found == 0 ) + { + Debug( 4, "Select timed out timeout was %d secs %d usecs", temp_timeout.tv_sec, temp_timeout.tv_usec ); + // Why are we disconnecting? It's just a timeout, meaning that data wasn't available. + //Disconnect(); + return( 0 ); + } + else if ( n_found < 0) + { + Error( "Select error: %s", strerror(errno) ); + return( -1 ); + } + + int total_bytes_to_read = 0; + + if ( bytes_expected ) + { + total_bytes_to_read = bytes_expected; + } + else + { + if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) { - Debug( 4, "Select timed out timeout was %d secs %d usecs", temp_timeout.tv_sec, temp_timeout.tv_usec ); - // Why are we disconnecting? It's just a timeout, meaning that data wasn't available. - //Disconnect(); - return( 0 ); - } - else if ( n_found < 0) - { - Error( "Select error: %s", strerror(errno) ); - return( -1 ); + Error( "Can't ioctl(): %s", strerror(errno) ); + return( -1 ); } - int total_bytes_to_read = 0; - - if ( bytes_expected ) + if ( total_bytes_to_read == 0 ) { - total_bytes_to_read = bytes_expected; + // If socket is closed locally, then select will fail, but if it is closed remotely + // then we have an exception on our socket.. but no data. + Debug( 3, "Socket closed remotely" ); + //Disconnect(); // Disconnect is done outside of ReadData now. + return( -1 ); } - else - { - if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) - { - Error( "Can't ioctl(): %s", strerror(errno) ); - return( -1 ); - } - if ( total_bytes_to_read == 0 ) - { - // If socket is closed locally, then select will fail, but if it is closed remotely - // then we have an exception on our socket.. but no data. - Debug( 3, "Socket closed remotely" ); - //Disconnect(); // Disconnect is done outside of ReadData now. - return( -1 ); - } - - // There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily. - if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) { - total_bytes_to_read = ZM_NETWORK_BUFSIZ; - Debug(3, "Just getting 32K" ); - } else { - Debug(3, "Just getting %d", total_bytes_to_read ); - } - } - Debug( 3, "Expecting %d bytes", total_bytes_to_read ); - - int total_bytes_read = 0; - do - { - int bytes_read = buffer.read_into( sd, total_bytes_to_read ); - if ( bytes_read < 0) - { - Error( "Read error: %s", strerror(errno) ); - return( -1 ); - } - else if ( bytes_read == 0) - { - Debug( 2, "Socket closed" ); - //Disconnect(); // Disconnect is done outside of ReadData now. - return( -1 ); - } - else if ( bytes_read < total_bytes_to_read ) - { - Error( "Incomplete read, expected %d, got %d", total_bytes_to_read, bytes_read ); - return( -1 ); - } - Debug( 3, "Read %d bytes", bytes_read ); - total_bytes_read += bytes_read; - total_bytes_to_read -= bytes_read; + // There can be lots of bytes available. I've seen 4MB or more. This will vastly inflate our buffer size unnecessarily. + if ( total_bytes_to_read > ZM_NETWORK_BUFSIZ ) { + total_bytes_to_read = ZM_NETWORK_BUFSIZ; + Debug(3, "Just getting 32K" ); + } else { + Debug(3, "Just getting %d", total_bytes_to_read ); } - while ( total_bytes_to_read ); + } + Debug( 3, "Expecting %d bytes", total_bytes_to_read ); - Debug( 4, buffer ); + int total_bytes_read = 0; + do + { + int bytes_read = buffer.read_into( sd, total_bytes_to_read ); + if ( bytes_read < 0) + { + Error( "Read error: %s", strerror(errno) ); + return( -1 ); + } + else if ( bytes_read == 0) + { + Debug( 2, "Socket closed" ); + //Disconnect(); // Disconnect is done outside of ReadData now. + return( -1 ); + } + else if ( bytes_read < total_bytes_to_read ) + { + Error( "Incomplete read, expected %d, got %d", total_bytes_to_read, bytes_read ); + return( -1 ); + } + Debug( 3, "Read %d bytes", bytes_read ); + total_bytes_read += bytes_read; + total_bytes_to_read -= bytes_read; + } + while ( total_bytes_to_read ); - return( total_bytes_read ); + Debug( 4, buffer ); + + return( total_bytes_read ); } int RemoteCameraHttp::GetResponse() { - int buffer_len; + int buffer_len; #if HAVE_LIBPCRE + if ( method == REGEXP ) + { + const char *header = 0; + int header_len = 0; + const char *http_version = 0; + int status_code = 0; + const char *status_mesg = 0; + const char *connection_type = ""; + int content_length = 0; + const char *content_type = ""; + const char *content_boundary = ""; + const char *subheader = 0; + int subheader_len = 0; + //int subcontent_length = 0; + //const char *subcontent_type = ""; + + while ( true ) + { + switch( state ) + { + case HEADER : + { + static RegExpr *header_expr = 0; + static RegExpr *status_expr = 0; + static RegExpr *connection_expr = 0; + static RegExpr *content_length_expr = 0; + static RegExpr *content_type_expr = 0; + + while ( ! ( buffer_len = ReadData( buffer ) ) ) { + } + if ( buffer_len < 0 ) { + Error( "Unable to read header data" ); + return( -1 ); + } + if ( !header_expr ) + header_expr = new RegExpr( "^(.+?\r?\n\r?\n)", PCRE_DOTALL ); + if ( header_expr->Match( (char*)buffer, buffer.size() ) == 2 ) + { + header = header_expr->MatchString( 1 ); + header_len = header_expr->MatchLength( 1 ); + Debug( 4, "Captured header (%d bytes):\n'%s'", header_len, header ); + + if ( !status_expr ) + status_expr = new RegExpr( "^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE_CASELESS ); + if ( status_expr->Match( header, header_len ) < 4 ) + { + Error( "Unable to extract HTTP status from header" ); + return( -1 ); + } + http_version = status_expr->MatchString( 1 ); + status_code = atoi( status_expr->MatchString( 2 ) ); + status_mesg = status_expr->MatchString( 3 ); + + if ( status_code == 401 ) { + if ( mNeedAuth ) { + Error( "Failed authentication: " ); + return( -1 ); + } + mNeedAuth = true; + std::string Header = header; + + mAuthenticator->checkAuthResponse(Header); + if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) { + Debug( 2, "Need Digest Authentication" ); + request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); + request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); + request += stringtf( "Host: %s\r\n", host.c_str()); + if ( strcmp( config.http_version, "1.0" ) == 0 ) + request += stringtf( "Connection: Keep-Alive\r\n" ); + request += mAuthenticator->getAuthHeader( "GET", path.c_str() ); + request += "\r\n"; + + Debug( 2, "New request header: %s", request.c_str() ); + return( 0 ); + } + + } else if ( status_code < 200 || status_code > 299 ) { + Error( "Invalid response status %d: %s\n%s", status_code, status_mesg, (char *)buffer ); + return( -1 ); + } + Debug( 3, "Got status '%d' (%s), http version %s", status_code, status_mesg, http_version ); + + if ( !connection_expr ) + connection_expr = new RegExpr( "Connection: ?(.+?)\r?\n", PCRE_CASELESS ); + if ( connection_expr->Match( header, header_len ) == 2 ) + { + connection_type = connection_expr->MatchString( 1 ); + Debug( 3, "Got connection '%s'", connection_type ); + } + + if ( !content_length_expr ) + content_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); + if ( content_length_expr->Match( header, header_len ) == 2 ) + { + content_length = atoi( content_length_expr->MatchString( 1 ) ); + Debug( 3, "Got content length '%d'", content_length ); + } + + if ( !content_type_expr ) + content_type_expr = new RegExpr( "Content-type: ?(.+?)(?:; ?boundary=(.+?))?\r?\n", PCRE_CASELESS ); + if ( content_type_expr->Match( header, header_len ) >= 2 ) + { + content_type = content_type_expr->MatchString( 1 ); + Debug( 3, "Got content type '%s'\n", content_type ); + if ( content_type_expr->MatchCount() > 2 ) + { + content_boundary = content_type_expr->MatchString( 2 ); + Debug( 3, "Got content boundary '%s'", content_boundary ); + } + } + + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = JPEG; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGB; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGBZ; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) + { + // Image stream, so start processing + if ( !content_boundary[0] ) + { + Error( "No content boundary found in header '%s'", header ); + return( -1 ); + } + mode = MULTI_IMAGE; + state = SUBHEADER; + } + //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) + //{ + //// MPEG stream, coming soon! + //} + else + { + Error( "Unrecognised content type '%s'", content_type ); + return( -1 ); + } + buffer.consume( header_len ); + } + else + { + Debug( 3, "Unable to extract header from stream, retrying" ); + //return( -1 ); + } + break; + } + case SUBHEADER : + { + static RegExpr *subheader_expr = 0; + static RegExpr *subcontent_length_expr = 0; + static RegExpr *subcontent_type_expr = 0; + + if ( !subheader_expr ) + { + char subheader_pattern[256] = ""; + snprintf( subheader_pattern, sizeof(subheader_pattern), "^((?:\r?\n){0,2}?(?:--)?%s\r?\n.+?\r?\n\r?\n)", content_boundary ); + subheader_expr = new RegExpr( subheader_pattern, PCRE_DOTALL ); + } + if ( subheader_expr->Match( (char *)buffer, (int)buffer ) == 2 ) + { + subheader = subheader_expr->MatchString( 1 ); + subheader_len = subheader_expr->MatchLength( 1 ); + Debug( 4, "Captured subheader (%d bytes):'%s'", subheader_len, subheader ); + + if ( !subcontent_length_expr ) + subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); + if ( subcontent_length_expr->Match( subheader, subheader_len ) == 2 ) + { + content_length = atoi( subcontent_length_expr->MatchString( 1 ) ); + Debug( 3, "Got subcontent length '%d'", content_length ); + } + + if ( !subcontent_type_expr ) + subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE_CASELESS ); + if ( subcontent_type_expr->Match( subheader, subheader_len ) == 2 ) + { + content_type = subcontent_type_expr->MatchString( 1 ); + Debug( 3, "Got subcontent type '%s'", content_type ); + } + + buffer.consume( subheader_len ); + state = CONTENT; + } + else + { + Debug( 3, "Unable to extract subheader from stream, retrying" ); + while ( ! ( buffer_len = ReadData( buffer ) ) ) { + } + if ( buffer_len < 0 ) { + Error( "Unable to extract subheader data" ); + return( -1 ); + } + } + break; + } + case CONTENT : + { + + // if content_type is something like image/jpeg;size=, this will strip the ;size= + char * semicolon = strchr( (char *)content_type, ';' ); + if ( semicolon ) { + *semicolon = '\0'; + } + + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + format = JPEG; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + format = X_RGB; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + format = X_RGBZ; + } + else + { + Error( "Found unsupported content type '%s'", content_type ); + return( -1 ); + } + + if ( content_length ) + { + while ( (long)buffer.size() < content_length ) + { +Debug(3, "Need more data buffer %d < content length %d", buffer.size(), content_length ); + if ( ReadData( buffer ) < 0 ) { + Error( "Unable to read content" ); + return( -1 ); + } + } + Debug( 3, "Got end of image by length, content-length = %d", content_length ); + } + else + { + while ( !content_length ) + { + while ( ! ( buffer_len = ReadData( buffer ) ) ) { + } + if ( buffer_len < 0 ) { + Error( "Unable to read content" ); + return( -1 ); + } + static RegExpr *content_expr = 0; + if ( mode == MULTI_IMAGE ) + { + if ( !content_expr ) + { + char content_pattern[256] = ""; + snprintf( content_pattern, sizeof(content_pattern), "^(.+?)(?:\r?\n)*(?:--)?%s\r?\n", content_boundary ); + content_expr = new RegExpr( content_pattern, PCRE_DOTALL ); + } + if ( content_expr->Match( buffer, buffer.size() ) == 2 ) + { + content_length = content_expr->MatchLength( 1 ); + Debug( 3, "Got end of image by pattern, content-length = %d", content_length ); + } + } + } + } + if ( mode == SINGLE_IMAGE ) + { + state = HEADER; + Disconnect(); + } + else + { + state = SUBHEADER; + } + Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() ); + return( content_length ); + } + case HEADERCONT : + case SUBHEADERCONT : + { + // Ignore + break; + } + } + } + } + else +#endif // HAVE_LIBPCRE + { if ( method == REGEXP ) { - const char *header = 0; - int header_len = 0; - const char *http_version = 0; - int status_code = 0; - const char *status_mesg = 0; - const char *connection_type = ""; - int content_length = 0; - const char *content_type = ""; - const char *content_boundary = ""; - const char *subheader = 0; - int subheader_len = 0; - //int subcontent_length = 0; - //const char *subcontent_type = ""; - - while ( true ) - { - switch( state ) - { - case HEADER : - { - static RegExpr *header_expr = 0; - static RegExpr *status_expr = 0; - static RegExpr *connection_expr = 0; - static RegExpr *content_length_expr = 0; - static RegExpr *content_type_expr = 0; - - while ( ! ( buffer_len = ReadData( buffer ) ) ) { - } - if ( buffer_len < 0 ) { - Error( "Unable to read header data" ); - return( -1 ); - } - if ( !header_expr ) - header_expr = new RegExpr( "^(.+?\r?\n\r?\n)", PCRE_DOTALL ); - if ( header_expr->Match( (char*)buffer, buffer.size() ) == 2 ) - { - header = header_expr->MatchString( 1 ); - header_len = header_expr->MatchLength( 1 ); - Debug( 4, "Captured header (%d bytes):\n'%s'", header_len, header ); - - if ( !status_expr ) - status_expr = new RegExpr( "^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE_CASELESS ); - if ( status_expr->Match( header, header_len ) < 4 ) - { - Error( "Unable to extract HTTP status from header" ); - return( -1 ); - } - http_version = status_expr->MatchString( 1 ); - status_code = atoi( status_expr->MatchString( 2 ) ); - status_mesg = status_expr->MatchString( 3 ); - - if ( status_code == 401 ) { - if ( mNeedAuth ) { - Error( "Failed authentication: " ); - return( -1 ); - } - mNeedAuth = true; - std::string Header = header; - - mAuthenticator->checkAuthResponse(Header); - if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) { - Debug( 2, "Need Digest Authentication" ); - request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); - request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); - request += stringtf( "Host: %s\r\n", host.c_str()); - if ( strcmp( config.http_version, "1.0" ) == 0 ) - request += stringtf( "Connection: Keep-Alive\r\n" ); - request += mAuthenticator->getAuthHeader( "GET", path.c_str() ); - request += "\r\n"; - - Debug( 2, "New request header: %s", request.c_str() ); - return( 0 ); - } - - } else if ( status_code < 200 || status_code > 299 ) { - Error( "Invalid response status %d: %s\n%s", status_code, status_mesg, (char *)buffer ); - return( -1 ); - } - Debug( 3, "Got status '%d' (%s), http version %s", status_code, status_mesg, http_version ); - - if ( !connection_expr ) - connection_expr = new RegExpr( "Connection: ?(.+?)\r?\n", PCRE_CASELESS ); - if ( connection_expr->Match( header, header_len ) == 2 ) - { - connection_type = connection_expr->MatchString( 1 ); - Debug( 3, "Got connection '%s'", connection_type ); - } - - if ( !content_length_expr ) - content_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); - if ( content_length_expr->Match( header, header_len ) == 2 ) - { - content_length = atoi( content_length_expr->MatchString( 1 ) ); - Debug( 3, "Got content length '%d'", content_length ); - } - - if ( !content_type_expr ) - content_type_expr = new RegExpr( "Content-type: ?(.+?)(?:; ?boundary=(.+?))?\r?\n", PCRE_CASELESS ); - if ( content_type_expr->Match( header, header_len ) >= 2 ) - { - content_type = content_type_expr->MatchString( 1 ); - Debug( 3, "Got content type '%s'\n", content_type ); - if ( content_type_expr->MatchCount() > 2 ) - { - content_boundary = content_type_expr->MatchString( 2 ); - Debug( 3, "Got content boundary '%s'", content_boundary ); - } - } - - if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) - { - // Single image - mode = SINGLE_IMAGE; - format = JPEG; - state = CONTENT; - } - else if ( !strcasecmp( content_type, "image/x-rgb" ) ) - { - // Single image - mode = SINGLE_IMAGE; - format = X_RGB; - state = CONTENT; - } - else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) - { - // Single image - mode = SINGLE_IMAGE; - format = X_RGBZ; - state = CONTENT; - } - else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) - { - // Image stream, so start processing - if ( !content_boundary[0] ) - { - Error( "No content boundary found in header '%s'", header ); - return( -1 ); - } - mode = MULTI_IMAGE; - state = SUBHEADER; - } - //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) - //{ - //// MPEG stream, coming soon! - //} - else - { - Error( "Unrecognised content type '%s'", content_type ); - return( -1 ); - } - buffer.consume( header_len ); - } - else - { - Debug( 3, "Unable to extract header from stream, retrying" ); - //return( -1 ); - } - break; - } - case SUBHEADER : - { - static RegExpr *subheader_expr = 0; - static RegExpr *subcontent_length_expr = 0; - static RegExpr *subcontent_type_expr = 0; - - if ( !subheader_expr ) - { - char subheader_pattern[256] = ""; - snprintf( subheader_pattern, sizeof(subheader_pattern), "^((?:\r?\n){0,2}?(?:--)?%s\r?\n.+?\r?\n\r?\n)", content_boundary ); - subheader_expr = new RegExpr( subheader_pattern, PCRE_DOTALL ); - } - if ( subheader_expr->Match( (char *)buffer, (int)buffer ) == 2 ) - { - subheader = subheader_expr->MatchString( 1 ); - subheader_len = subheader_expr->MatchLength( 1 ); - Debug( 4, "Captured subheader (%d bytes):'%s'", subheader_len, subheader ); - - if ( !subcontent_length_expr ) - subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); - if ( subcontent_length_expr->Match( subheader, subheader_len ) == 2 ) - { - content_length = atoi( subcontent_length_expr->MatchString( 1 ) ); - Debug( 3, "Got subcontent length '%d'", content_length ); - } - - if ( !subcontent_type_expr ) - subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE_CASELESS ); - if ( subcontent_type_expr->Match( subheader, subheader_len ) == 2 ) - { - content_type = subcontent_type_expr->MatchString( 1 ); - Debug( 3, "Got subcontent type '%s'", content_type ); - } - - buffer.consume( subheader_len ); - state = CONTENT; - } - else - { - Debug( 3, "Unable to extract subheader from stream, retrying" ); - while ( ! ( buffer_len = ReadData( buffer ) ) ) { - } - if ( buffer_len < 0 ) { - Error( "Unable to extract subheader data" ); - return( -1 ); - } - } - break; - } - case CONTENT : - { - - // if content_type is something like image/jpeg;size=, this will strip the ;size= - char * semicolon = strchr( (char *)content_type, ';' ); - if ( semicolon ) { - *semicolon = '\0'; - } - - if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) - { - format = JPEG; - } - else if ( !strcasecmp( content_type, "image/x-rgb" ) ) - { - format = X_RGB; - } - else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) - { - format = X_RGBZ; - } - else - { - Error( "Found unsupported content type '%s'", content_type ); - return( -1 ); - } - - if ( content_length ) - { - while ( (long)buffer.size() < content_length ) - { -Debug(3, "Need more data buffer %d < content length %d", buffer.size(), content_length ); - if ( ReadData( buffer ) < 0 ) { - Error( "Unable to read content" ); - return( -1 ); - } - } - Debug( 3, "Got end of image by length, content-length = %d", content_length ); - } - else - { - while ( !content_length ) - { - while ( ! ( buffer_len = ReadData( buffer ) ) ) { - } - if ( buffer_len < 0 ) { - Error( "Unable to read content" ); - return( -1 ); - } - static RegExpr *content_expr = 0; - if ( mode == MULTI_IMAGE ) - { - if ( !content_expr ) - { - char content_pattern[256] = ""; - snprintf( content_pattern, sizeof(content_pattern), "^(.+?)(?:\r?\n)*(?:--)?%s\r?\n", content_boundary ); - content_expr = new RegExpr( content_pattern, PCRE_DOTALL ); - } - if ( content_expr->Match( buffer, buffer.size() ) == 2 ) - { - content_length = content_expr->MatchLength( 1 ); - Debug( 3, "Got end of image by pattern, content-length = %d", content_length ); - } - } - } - } - if ( mode == SINGLE_IMAGE ) - { - state = HEADER; - Disconnect(); - } - else - { - state = SUBHEADER; - } - Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() ); - return( content_length ); - } - case HEADERCONT : - case SUBHEADERCONT : - { - // Ignore - break; - } - } - } + Warning( "Unable to use netcam regexps as not compiled with libpcre" ); } - else -#endif // HAVE_LIBPCRE + static const char *http_match = "HTTP/"; + static const char *connection_match = "Connection:"; + static const char *content_length_match = "Content-length:"; + static const char *content_type_match = "Content-type:"; + static const char *boundary_match = "boundary="; + static const char *authenticate_match = "WWW-Authenticate:"; + static int http_match_len = 0; + static int connection_match_len = 0; + static int content_length_match_len = 0; + static int content_type_match_len = 0; + static int boundary_match_len = 0; + static int authenticate_match_len = 0; + + if ( !http_match_len ) + http_match_len = strlen( http_match ); + if ( !connection_match_len ) + connection_match_len = strlen( connection_match ); + if ( !content_length_match_len ) + content_length_match_len = strlen( content_length_match ); + if ( !content_type_match_len ) + content_type_match_len = strlen( content_type_match ); + if ( !boundary_match_len ) + boundary_match_len = strlen( boundary_match ); + if ( !authenticate_match_len ) + authenticate_match_len = strlen( authenticate_match ); + + static int n_headers; + //static char *headers[32]; + + static int n_subheaders; + //static char *subheaders[32]; + + static char *http_header; + static char *connection_header; + static char *content_length_header; + static char *content_type_header; + static char *boundary_header; + static char *authenticate_header; + static char subcontent_length_header[32]; + static char subcontent_type_header[64]; + + static char http_version[16]; + static char status_code[16]; + static char status_mesg[256]; + static char connection_type[32]; + static int content_length; + static char content_type[32]; + static char content_boundary[64]; + static int content_boundary_len; + + while ( true ) { - if ( method == REGEXP ) + switch( state ) + { + case HEADER : { - Warning( "Unable to use netcam regexps as not compiled with libpcre" ); + n_headers = 0; + http_header = 0; + connection_header = 0; + content_length_header = 0; + content_type_header = 0; + authenticate_header = 0; + + http_version[0] = '\0'; + status_code [0]= '\0'; + status_mesg [0]= '\0'; + connection_type [0]= '\0'; + content_length = 0; + content_type[0] = '\0'; + content_boundary[0] = '\0'; + content_boundary_len = 0; } - static const char *http_match = "HTTP/"; - static const char *connection_match = "Connection:"; - static const char *content_length_match = "Content-length:"; - static const char *content_type_match = "Content-type:"; - static const char *boundary_match = "boundary="; - static const char *authenticate_match = "WWW-Authenticate:"; - static int http_match_len = 0; - static int connection_match_len = 0; - static int content_length_match_len = 0; - static int content_type_match_len = 0; - static int boundary_match_len = 0; - static int authenticate_match_len = 0; - - if ( !http_match_len ) - http_match_len = strlen( http_match ); - if ( !connection_match_len ) - connection_match_len = strlen( connection_match ); - if ( !content_length_match_len ) - content_length_match_len = strlen( content_length_match ); - if ( !content_type_match_len ) - content_type_match_len = strlen( content_type_match ); - if ( !boundary_match_len ) - boundary_match_len = strlen( boundary_match ); - if ( !authenticate_match_len ) - authenticate_match_len = strlen( authenticate_match ); - - static int n_headers; - //static char *headers[32]; - - static int n_subheaders; - //static char *subheaders[32]; - - static char *http_header; - static char *connection_header; - static char *content_length_header; - static char *content_type_header; - static char *boundary_header; - static char *authenticate_header; - static char subcontent_length_header[32]; - static char subcontent_type_header[64]; - - static char http_version[16]; - static char status_code[16]; - static char status_mesg[256]; - static char connection_type[32]; - static int content_length; - static char content_type[32]; - static char content_boundary[64]; - static int content_boundary_len; - - while ( true ) + case HEADERCONT : { - switch( state ) - { - case HEADER : - { - n_headers = 0; - http_header = 0; - connection_header = 0; - content_length_header = 0; - content_type_header = 0; - authenticate_header = 0; - - http_version[0] = '\0'; - status_code [0]= '\0'; - status_mesg [0]= '\0'; - connection_type [0]= '\0'; - content_length = 0; - content_type[0] = '\0'; - content_boundary[0] = '\0'; - content_boundary_len = 0; - } - case HEADERCONT : - { - while ( ! ( buffer_len = ReadData( buffer ) ) ) { - } - if ( buffer_len < 0 ) { - Error( "Unable to read header" ); - return( -1 ); - } - - char *crlf = 0; - char *header_ptr = (char *)buffer; - int header_len = buffer.size(); - bool all_headers = false; - - while( true ) - { - int crlf_len = memspn( header_ptr, "\r\n", header_len ); - if ( n_headers ) - { - if ( (crlf_len == 2 && !strncmp( header_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( header_ptr, "\r\n\r\n", crlf_len )) ) - { - *header_ptr = '\0'; - header_ptr += crlf_len; - header_len -= buffer.consume( header_ptr-(char *)buffer ); - all_headers = true; - break; - } - } - if ( crlf_len ) - { - if ( header_len == crlf_len ) - { - break; - } - else - { - *header_ptr = '\0'; - header_ptr += crlf_len; - header_len -= buffer.consume( header_ptr-(char *)buffer ); - } - } - - Debug( 6, "%s", header_ptr ); - if ( (crlf = mempbrk( header_ptr, "\r\n", header_len )) ) - { - //headers[n_headers++] = header_ptr; - n_headers++; - - if ( !http_header && (strncasecmp( header_ptr, http_match, http_match_len ) == 0) ) - { - http_header = header_ptr+http_match_len; - Debug( 6, "Got http header '%s'", header_ptr ); - } - else if ( !connection_header && (strncasecmp( header_ptr, connection_match, connection_match_len) == 0) ) - { - connection_header = header_ptr+connection_match_len; - Debug( 6, "Got connection header '%s'", header_ptr ); - } - else if ( !content_length_header && (strncasecmp( header_ptr, content_length_match, content_length_match_len) == 0) ) - { - content_length_header = header_ptr+content_length_match_len; - Debug( 6, "Got content length header '%s'", header_ptr ); - } - - else if ( !authenticate_header && (strncasecmp( header_ptr, authenticate_match, authenticate_match_len) == 0) ) - { - authenticate_header = header_ptr; - Debug( 6, "Got authenticate header '%s'", header_ptr ); - } - else if ( !content_type_header && (strncasecmp( header_ptr, content_type_match, content_type_match_len) == 0) ) - { - content_type_header = header_ptr+content_type_match_len; - Debug( 6, "Got content type header '%s'", header_ptr ); - } - else - { - Debug( 6, "Got ignored header '%s'", header_ptr ); - } - header_ptr = crlf; - header_len -= buffer.consume( header_ptr-(char *)buffer ); - } - else - { - // No end of line found - break; - } - } - - if ( all_headers ) - { - char *start_ptr, *end_ptr; - - if ( !http_header ) - { - Error( "Unable to extract HTTP status from header" ); - return( -1 ); - } - - start_ptr = http_header; - end_ptr = start_ptr+strspn( start_ptr, "10." ); - - memset( http_version, 0, sizeof(http_version) ); - strncpy( http_version, start_ptr, end_ptr-start_ptr ); - - start_ptr = end_ptr; - start_ptr += strspn( start_ptr, " " ); - end_ptr = start_ptr+strspn( start_ptr, "0123456789" ); - - memset( status_code, 0, sizeof(status_code) ); - strncpy( status_code, start_ptr, end_ptr-start_ptr ); - int status = atoi( status_code ); - - start_ptr = end_ptr; - start_ptr += strspn( start_ptr, " " ); - strcpy( status_mesg, start_ptr ); - - if ( status == 401 ) { - if ( mNeedAuth ) { - Error( "Failed authentication: " ); - return( -1 ); - } - if ( ! authenticate_header ) { - Error( "Failed authentication, but don't have an authentication header: " ); - return( -1 ); - } - mNeedAuth = true; - std::string Header = authenticate_header; - Debug(2, "Checking for digest auth in %s", authenticate_header ); - - mAuthenticator->checkAuthResponse(Header); - if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) { - Debug( 2, "Need Digest Authentication" ); - request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); - request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); - request += stringtf( "Host: %s\r\n", host.c_str()); - if ( strcmp( config.http_version, "1.0" ) == 0 ) - request += stringtf( "Connection: Keep-Alive\r\n" ); - request += mAuthenticator->getAuthHeader( "GET", path.c_str() ); - request += "\r\n"; - - Debug( 2, "New request header: %s", request.c_str() ); - return( 0 ); - } else { - Debug( 2, "Need some other kind of Authentication" ); - } - } else if ( status < 200 || status > 299 ) - { - Error( "Invalid response status %s: %s", status_code, status_mesg ); - return( -1 ); - } - Debug( 3, "Got status '%d' (%s), http version %s", status, status_mesg, http_version ); - - if ( connection_header ) - { - memset( connection_type, 0, sizeof(connection_type) ); - start_ptr = connection_header + strspn( connection_header, " " ); - strcpy( connection_type, start_ptr ); - Debug( 3, "Got connection '%s'", connection_type ); - } - if ( content_length_header ) - { - start_ptr = content_length_header + strspn( content_length_header, " " ); - content_length = atoi( start_ptr ); - Debug( 3, "Got content length '%d'", content_length ); - } - if ( content_type_header ) - { - memset( content_type, 0, sizeof(content_type) ); - start_ptr = content_type_header + strspn( content_type_header, " " ); - if ( (end_ptr = strchr( start_ptr, ';' )) ) - { - strncpy( content_type, start_ptr, end_ptr-start_ptr ); - Debug( 3, "Got content type '%s'", content_type ); - - start_ptr = end_ptr + strspn( end_ptr, "; " ); - - if ( strncasecmp( start_ptr, boundary_match, boundary_match_len ) == 0 ) - { - start_ptr += boundary_match_len; - start_ptr += strspn( start_ptr, "-" ); - content_boundary_len = sprintf( content_boundary, "--%s", start_ptr ); - Debug( 3, "Got content boundary '%s'", content_boundary ); - } - else - { - Error( "No content boundary found in header '%s'", content_type_header ); - } - } - else - { - strcpy( content_type, start_ptr ); - Debug( 3, "Got content type '%s'", content_type ); - } - } - - if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) - { - // Single image - mode = SINGLE_IMAGE; - format = JPEG; - state = CONTENT; - } - else if ( !strcasecmp( content_type, "image/x-rgb" ) ) - { - // Single image - mode = SINGLE_IMAGE; - format = X_RGB; - state = CONTENT; - } - else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) - { - // Single image - mode = SINGLE_IMAGE; - format = X_RGBZ; - state = CONTENT; - } - else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) - { - // Image stream, so start processing - if ( !content_boundary[0] ) - { - Error( "No content boundary found in header '%s'", content_type_header ); - return( -1 ); - } - mode = MULTI_IMAGE; - state = SUBHEADER; - } - //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) - //{ - //// MPEG stream, coming soon! - //} - else - { - Error( "Unrecognised content type '%s'", content_type ); - return( -1 ); - } - } - else - { - Debug( 3, "Unable to extract entire header from stream, continuing" ); - state = HEADERCONT; - //return( -1 ); - } - break; - } - case SUBHEADER : - { - n_subheaders = 0; - boundary_header = 0; - subcontent_length_header[0] = '\0'; - subcontent_type_header[0] = '\0'; - content_length = 0; - content_type[0] = '\0'; - } - case SUBHEADERCONT : - { - char *crlf = 0; - char *subheader_ptr = (char *)buffer; - int subheader_len = buffer.size(); - bool all_headers = false; - - while( true ) - { - int crlf_len = memspn( subheader_ptr, "\r\n", subheader_len ); - if ( n_subheaders ) - { - if ( (crlf_len == 2 && !strncmp( subheader_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( subheader_ptr, "\r\n\r\n", crlf_len )) ) - { - *subheader_ptr = '\0'; - subheader_ptr += crlf_len; - subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); - all_headers = true; - break; - } - } - if ( crlf_len ) - { - if ( subheader_len == crlf_len ) - { - break; - } - else - { - *subheader_ptr = '\0'; - subheader_ptr += crlf_len; - subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); - } - } - - Debug( 6, "%d: %s", subheader_len, subheader_ptr ); - - if ( (crlf = mempbrk( subheader_ptr, "\r\n", subheader_len )) ) - { - //subheaders[n_subheaders++] = subheader_ptr; - n_subheaders++; - - if ( !boundary_header && (strncasecmp( subheader_ptr, content_boundary, content_boundary_len ) == 0) ) - { - boundary_header = subheader_ptr; - Debug( 4, "Got boundary subheader '%s'", subheader_ptr ); - } - else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) ) - { - strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) ); - *(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0'; - Debug( 4, "Got content length subheader '%s'", subcontent_length_header ); - } - else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) ) - { - strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) ); - *(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0'; - Debug( 4, "Got content type subheader '%s'", subcontent_type_header ); - } - else - { - Debug( 6, "Got ignored subheader '%s' found", subheader_ptr ); - } - subheader_ptr = crlf; - subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); - } - else - { - // No line end found - break; - } - } - - if ( all_headers && boundary_header ) - { - char *start_ptr/*, *end_ptr*/; - - Debug( 3, "Got boundary '%s'", boundary_header ); - - if ( subcontent_length_header[0] ) - { - start_ptr = subcontent_length_header + strspn( subcontent_length_header, " " ); - content_length = atoi( start_ptr ); - Debug( 3, "Got subcontent length '%d'", content_length ); - } - if ( subcontent_type_header[0] ) - { - memset( content_type, 0, sizeof(content_type) ); - start_ptr = subcontent_type_header + strspn( subcontent_type_header, " " ); - strcpy( content_type, start_ptr ); - Debug( 3, "Got subcontent type '%s'", content_type ); - } - state = CONTENT; - } - else - { - Debug( 3, "Unable to extract subheader from stream, retrying" ); - while ( ! ( buffer_len = ReadData( buffer ) ) ) { - } - if ( buffer_len < 0 ) { - Error( "Unable to read subheader" ); - return( -1 ); - } - state = SUBHEADERCONT; - } - break; - } - case CONTENT : - { - - // if content_type is something like image/jpeg;size=, this will strip the ;size= - char * semicolon = strchr( content_type, ';' ); - if ( semicolon ) { - *semicolon = '\0'; - } - - if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) - { - format = JPEG; - } - else if ( !strcasecmp( content_type, "image/x-rgb" ) ) - { - format = X_RGB; - } - else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) - { - format = X_RGBZ; - } - else - { - Error( "Found unsupported content type '%s'", content_type ); - return( -1 ); - } - - if ( format == JPEG && buffer.size() >= 2 ) - { - if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) - { - Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); - return( -1 ); - } - } - - if ( content_length ) - { - while ( (long)buffer.size() < content_length ) - { - //int buffer_len = ReadData( buffer, content_length-buffer.size() ); - if ( ReadData( buffer ) < 0 ) { - Error( "Unable to read content" ); - return( -1 ); - } - } - Debug( 3, "Got end of image by length, content-length = %d", content_length ); - } - else - { - int content_pos = 0; - while ( !content_length ) - { - buffer_len = ReadData( buffer ); - if ( buffer_len < 0 ) - { - Error( "Unable to read content" ); - return( -1 ); - } - int buffer_size = buffer.size(); - if ( buffer_len ) - { - if ( mode == MULTI_IMAGE ) - { - while ( char *start_ptr = (char *)memstr( (char *)buffer+content_pos, "\r\n--", buffer_size-content_pos ) ) - { - content_length = start_ptr - (char *)buffer; - Debug( 3, "Got end of image by pattern (crlf--), content-length = %d", content_length ); - break; - } - } - } - else - { - content_length = buffer_size; - Debug( 3, "Got end of image by closure, content-length = %d", content_length ); - if ( mode == SINGLE_IMAGE ) - { - char *end_ptr = (char *)buffer+buffer_size; - - while( *end_ptr == '\r' || *end_ptr == '\n' ) - { - content_length--; - end_ptr--; - } - - if ( end_ptr != ((char *)buffer+buffer_size) ) - { - Debug( 3, "Trimmed end of image, new content-length = %d", content_length ); - } - } - } - } - } - if ( mode == SINGLE_IMAGE ) - { - state = HEADER; - Disconnect(); - } - else - { - state = SUBHEADER; - } - - if ( format == JPEG && buffer.size() >= 2 ) - { - if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) - { - Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); - return( -1 ); - } - } - - Debug( 3, "Returning %d bytes, buffer size: (%d) bytes of captured content", content_length, buffer.size() ); - return( content_length ); - } + while ( ! ( buffer_len = ReadData( buffer ) ) ) { + } + if ( buffer_len < 0 ) { + Error( "Unable to read header" ); + return( -1 ); } + + char *crlf = 0; + char *header_ptr = (char *)buffer; + int header_len = buffer.size(); + bool all_headers = false; + + while( true ) + { + int crlf_len = memspn( header_ptr, "\r\n", header_len ); + if ( n_headers ) + { + if ( (crlf_len == 2 && !strncmp( header_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( header_ptr, "\r\n\r\n", crlf_len )) ) + { + *header_ptr = '\0'; + header_ptr += crlf_len; + header_len -= buffer.consume( header_ptr-(char *)buffer ); + all_headers = true; + break; + } + } + if ( crlf_len ) + { + if ( header_len == crlf_len ) + { + break; + } + else + { + *header_ptr = '\0'; + header_ptr += crlf_len; + header_len -= buffer.consume( header_ptr-(char *)buffer ); + } + } + + Debug( 6, "%s", header_ptr ); + if ( (crlf = mempbrk( header_ptr, "\r\n", header_len )) ) + { + //headers[n_headers++] = header_ptr; + n_headers++; + + if ( !http_header && (strncasecmp( header_ptr, http_match, http_match_len ) == 0) ) + { + http_header = header_ptr+http_match_len; + Debug( 6, "Got http header '%s'", header_ptr ); + } + else if ( !connection_header && (strncasecmp( header_ptr, connection_match, connection_match_len) == 0) ) + { + connection_header = header_ptr+connection_match_len; + Debug( 6, "Got connection header '%s'", header_ptr ); + } + else if ( !content_length_header && (strncasecmp( header_ptr, content_length_match, content_length_match_len) == 0) ) + { + content_length_header = header_ptr+content_length_match_len; + Debug( 6, "Got content length header '%s'", header_ptr ); + } + + else if ( !authenticate_header && (strncasecmp( header_ptr, authenticate_match, authenticate_match_len) == 0) ) + { + authenticate_header = header_ptr; + Debug( 6, "Got authenticate header '%s'", header_ptr ); + } + else if ( !content_type_header && (strncasecmp( header_ptr, content_type_match, content_type_match_len) == 0) ) + { + content_type_header = header_ptr+content_type_match_len; + Debug( 6, "Got content type header '%s'", header_ptr ); + } + else + { + Debug( 6, "Got ignored header '%s'", header_ptr ); + } + header_ptr = crlf; + header_len -= buffer.consume( header_ptr-(char *)buffer ); + } + else + { + // No end of line found + break; + } + } + + if ( all_headers ) + { + char *start_ptr, *end_ptr; + + if ( !http_header ) + { + Error( "Unable to extract HTTP status from header" ); + return( -1 ); + } + + start_ptr = http_header; + end_ptr = start_ptr+strspn( start_ptr, "10." ); + + memset( http_version, 0, sizeof(http_version) ); + strncpy( http_version, start_ptr, end_ptr-start_ptr ); + + start_ptr = end_ptr; + start_ptr += strspn( start_ptr, " " ); + end_ptr = start_ptr+strspn( start_ptr, "0123456789" ); + + memset( status_code, 0, sizeof(status_code) ); + strncpy( status_code, start_ptr, end_ptr-start_ptr ); + int status = atoi( status_code ); + + start_ptr = end_ptr; + start_ptr += strspn( start_ptr, " " ); + strcpy( status_mesg, start_ptr ); + + if ( status == 401 ) { + if ( mNeedAuth ) { + Error( "Failed authentication: " ); + return( -1 ); + } + if ( ! authenticate_header ) { + Error( "Failed authentication, but don't have an authentication header: " ); + return( -1 ); + } + mNeedAuth = true; + std::string Header = authenticate_header; + Debug(2, "Checking for digest auth in %s", authenticate_header ); + + mAuthenticator->checkAuthResponse(Header); + if ( mAuthenticator->auth_method() == zm::AUTH_DIGEST ) { + Debug( 2, "Need Digest Authentication" ); + request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); + request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); + request += stringtf( "Host: %s\r\n", host.c_str()); + if ( strcmp( config.http_version, "1.0" ) == 0 ) + request += stringtf( "Connection: Keep-Alive\r\n" ); + request += mAuthenticator->getAuthHeader( "GET", path.c_str() ); + request += "\r\n"; + + Debug( 2, "New request header: %s", request.c_str() ); + return( 0 ); + } else { + Debug( 2, "Need some other kind of Authentication" ); + } + } else if ( status < 200 || status > 299 ) + { + Error( "Invalid response status %s: %s", status_code, status_mesg ); + return( -1 ); + } + Debug( 3, "Got status '%d' (%s), http version %s", status, status_mesg, http_version ); + + if ( connection_header ) + { + memset( connection_type, 0, sizeof(connection_type) ); + start_ptr = connection_header + strspn( connection_header, " " ); + strcpy( connection_type, start_ptr ); + Debug( 3, "Got connection '%s'", connection_type ); + } + if ( content_length_header ) + { + start_ptr = content_length_header + strspn( content_length_header, " " ); + content_length = atoi( start_ptr ); + Debug( 3, "Got content length '%d'", content_length ); + } + if ( content_type_header ) + { + memset( content_type, 0, sizeof(content_type) ); + start_ptr = content_type_header + strspn( content_type_header, " " ); + if ( (end_ptr = strchr( start_ptr, ';' )) ) + { + strncpy( content_type, start_ptr, end_ptr-start_ptr ); + Debug( 3, "Got content type '%s'", content_type ); + + start_ptr = end_ptr + strspn( end_ptr, "; " ); + + if ( strncasecmp( start_ptr, boundary_match, boundary_match_len ) == 0 ) + { + start_ptr += boundary_match_len; + start_ptr += strspn( start_ptr, "-" ); + content_boundary_len = sprintf( content_boundary, "--%s", start_ptr ); + Debug( 3, "Got content boundary '%s'", content_boundary ); + } + else + { + Error( "No content boundary found in header '%s'", content_type_header ); + } + } + else + { + strcpy( content_type, start_ptr ); + Debug( 3, "Got content type '%s'", content_type ); + } + } + + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = JPEG; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGB; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGBZ; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) + { + // Image stream, so start processing + if ( !content_boundary[0] ) + { + Error( "No content boundary found in header '%s'", content_type_header ); + return( -1 ); + } + mode = MULTI_IMAGE; + state = SUBHEADER; + } + //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) + //{ + //// MPEG stream, coming soon! + //} + else + { + Error( "Unrecognised content type '%s'", content_type ); + return( -1 ); + } + } + else + { + Debug( 3, "Unable to extract entire header from stream, continuing" ); + state = HEADERCONT; + //return( -1 ); + } + break; } + case SUBHEADER : + { + n_subheaders = 0; + boundary_header = 0; + subcontent_length_header[0] = '\0'; + subcontent_type_header[0] = '\0'; + content_length = 0; + content_type[0] = '\0'; + } + case SUBHEADERCONT : + { + char *crlf = 0; + char *subheader_ptr = (char *)buffer; + int subheader_len = buffer.size(); + bool all_headers = false; + + while( true ) + { + int crlf_len = memspn( subheader_ptr, "\r\n", subheader_len ); + if ( n_subheaders ) + { + if ( (crlf_len == 2 && !strncmp( subheader_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( subheader_ptr, "\r\n\r\n", crlf_len )) ) + { + *subheader_ptr = '\0'; + subheader_ptr += crlf_len; + subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); + all_headers = true; + break; + } + } + if ( crlf_len ) + { + if ( subheader_len == crlf_len ) + { + break; + } + else + { + *subheader_ptr = '\0'; + subheader_ptr += crlf_len; + subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); + } + } + + Debug( 6, "%d: %s", subheader_len, subheader_ptr ); + + if ( (crlf = mempbrk( subheader_ptr, "\r\n", subheader_len )) ) + { + //subheaders[n_subheaders++] = subheader_ptr; + n_subheaders++; + + if ( !boundary_header && (strncasecmp( subheader_ptr, content_boundary, content_boundary_len ) == 0) ) + { + boundary_header = subheader_ptr; + Debug( 4, "Got boundary subheader '%s'", subheader_ptr ); + } + else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) ) + { + strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) ); + *(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0'; + Debug( 4, "Got content length subheader '%s'", subcontent_length_header ); + } + else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) ) + { + strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) ); + *(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0'; + Debug( 4, "Got content type subheader '%s'", subcontent_type_header ); + } + else + { + Debug( 6, "Got ignored subheader '%s' found", subheader_ptr ); + } + subheader_ptr = crlf; + subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); + } + else + { + // No line end found + break; + } + } + + if ( all_headers && boundary_header ) + { + char *start_ptr/*, *end_ptr*/; + + Debug( 3, "Got boundary '%s'", boundary_header ); + + if ( subcontent_length_header[0] ) + { + start_ptr = subcontent_length_header + strspn( subcontent_length_header, " " ); + content_length = atoi( start_ptr ); + Debug( 3, "Got subcontent length '%d'", content_length ); + } + if ( subcontent_type_header[0] ) + { + memset( content_type, 0, sizeof(content_type) ); + start_ptr = subcontent_type_header + strspn( subcontent_type_header, " " ); + strcpy( content_type, start_ptr ); + Debug( 3, "Got subcontent type '%s'", content_type ); + } + state = CONTENT; + } + else + { + Debug( 3, "Unable to extract subheader from stream, retrying" ); + while ( ! ( buffer_len = ReadData( buffer ) ) ) { + } + if ( buffer_len < 0 ) { + Error( "Unable to read subheader" ); + return( -1 ); + } + state = SUBHEADERCONT; + } + break; + } + case CONTENT : + { + + // if content_type is something like image/jpeg;size=, this will strip the ;size= + char * semicolon = strchr( content_type, ';' ); + if ( semicolon ) { + *semicolon = '\0'; + } + + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + format = JPEG; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + format = X_RGB; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + format = X_RGBZ; + } + else + { + Error( "Found unsupported content type '%s'", content_type ); + return( -1 ); + } + + if ( format == JPEG && buffer.size() >= 2 ) + { + if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) + { + Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); + return( -1 ); + } + } + + if ( content_length ) + { + while ( (long)buffer.size() < content_length ) + { + //int buffer_len = ReadData( buffer, content_length-buffer.size() ); + if ( ReadData( buffer ) < 0 ) { + Error( "Unable to read content" ); + return( -1 ); + } + } + Debug( 3, "Got end of image by length, content-length = %d", content_length ); + } + else + { + int content_pos = 0; + while ( !content_length ) + { + buffer_len = ReadData( buffer ); + if ( buffer_len < 0 ) + { + Error( "Unable to read content" ); + return( -1 ); + } + int buffer_size = buffer.size(); + if ( buffer_len ) + { + if ( mode == MULTI_IMAGE ) + { + while ( char *start_ptr = (char *)memstr( (char *)buffer+content_pos, "\r\n--", buffer_size-content_pos ) ) + { + content_length = start_ptr - (char *)buffer; + Debug( 3, "Got end of image by pattern (crlf--), content-length = %d", content_length ); + break; + } + } + } + else + { + content_length = buffer_size; + Debug( 3, "Got end of image by closure, content-length = %d", content_length ); + if ( mode == SINGLE_IMAGE ) + { + char *end_ptr = (char *)buffer+buffer_size; + + while( *end_ptr == '\r' || *end_ptr == '\n' ) + { + content_length--; + end_ptr--; + } + + if ( end_ptr != ((char *)buffer+buffer_size) ) + { + Debug( 3, "Trimmed end of image, new content-length = %d", content_length ); + } + } + } + } + } + if ( mode == SINGLE_IMAGE ) + { + state = HEADER; + Disconnect(); + } + else + { + state = SUBHEADER; + } + + if ( format == JPEG && buffer.size() >= 2 ) + { + if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) + { + Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); + return( -1 ); + } + } + + Debug( 3, "Returning %d bytes, buffer size: (%d) bytes of captured content", content_length, buffer.size() ); + return( content_length ); + } + } } - return( 0 ); + } + return( 0 ); } int RemoteCameraHttp::PreCapture() { + if ( sd < 0 ) + { + Connect(); if ( sd < 0 ) { - Connect(); - if ( sd < 0 ) - { - Error( "Unable to connect to camera" ); - return( -1 ); - } - mode = SINGLE_IMAGE; - buffer.clear(); + Error( "Unable to connect to camera" ); + return( -1 ); } - if ( mode == SINGLE_IMAGE ) + mode = SINGLE_IMAGE; + buffer.clear(); + } + if ( mode == SINGLE_IMAGE ) + { + if ( SendRequest() < 0 ) { - if ( SendRequest() < 0 ) - { - Error( "Unable to send request" ); - Disconnect(); - return( -1 ); - } + Error( "Unable to send request" ); + Disconnect(); + return( -1 ); } - return( 0 ); + } + return( 0 ); } int RemoteCameraHttp::Capture( Image &image ) { - int content_length = GetResponse(); - if ( content_length == 0 ) + int content_length = GetResponse(); + if ( content_length == 0 ) + { + Warning( "Unable to capture image, retrying" ); + return( 1 ); + } + if ( content_length < 0 ) + { + Error( "Unable to get response, disconnecting" ); + Disconnect(); + return( -1 ); + } + switch( format ) + { + case JPEG : { - Warning( "Unable to capture image, retrying" ); - return( 1 ); - } - if ( content_length < 0 ) - { - Error( "Unable to get response, disconnecting" ); + if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) ) + { + Error( "Unable to decode jpeg" ); Disconnect(); return( -1 ); + } + break; } - switch( format ) + case X_RGB : { - case JPEG : - { - if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) ) - { - Error( "Unable to decode jpeg" ); - Disconnect(); - return( -1 ); - } - break; - } - case X_RGB : - { - if ( content_length != (long)image.Size() ) - { - Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length ); - Disconnect(); - return( -1 ); - } - image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); - break; - } - case X_RGBZ : - { - if ( !image.Unzip( buffer.extract( content_length ), content_length ) ) - { - Error( "Unable to unzip RGB image" ); - Disconnect(); - return( -1 ); - } - image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); - break; - } - default : - { - Error( "Unexpected image format encountered" ); - Disconnect(); - return( -1 ); - } + if ( content_length != (long)image.Size() ) + { + Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length ); + Disconnect(); + return( -1 ); + } + image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); + break; } - return( 0 ); + case X_RGBZ : + { + if ( !image.Unzip( buffer.extract( content_length ), content_length ) ) + { + Error( "Unable to unzip RGB image" ); + Disconnect(); + return( -1 ); + } + image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); + break; + } + default : + { + Error( "Unexpected image format encountered" ); + Disconnect(); + return( -1 ); + } + } + return( 0 ); } int RemoteCameraHttp::PostCapture() { - return( 0 ); + return( 0 ); } diff --git a/src/zm_remote_camera_http.h b/src/zm_remote_camera_http.h index 5fe065cf9..bfadecce5 100644 --- a/src/zm_remote_camera_http.h +++ b/src/zm_remote_camera_http.h @@ -33,31 +33,31 @@ class RemoteCameraHttp : public RemoteCamera { protected: - std::string request; - struct timeval timeout; - //struct hostent *hp; - //struct sockaddr_in sa; - int sd; - Buffer buffer; - enum { SINGLE_IMAGE, MULTI_IMAGE } mode; - enum { UNDEF, JPEG, X_RGB, X_RGBZ } format; - enum { HEADER, HEADERCONT, SUBHEADER, SUBHEADERCONT, CONTENT } state; - enum { SIMPLE, REGEXP } method; + std::string request; + struct timeval timeout; + //struct hostent *hp; + //struct sockaddr_in sa; + int sd; + Buffer buffer; + enum { SINGLE_IMAGE, MULTI_IMAGE } mode; + enum { UNDEF, JPEG, X_RGB, X_RGBZ } format; + enum { HEADER, HEADERCONT, SUBHEADER, SUBHEADERCONT, CONTENT } state; + enum { SIMPLE, REGEXP } method; public: - RemoteCameraHttp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - ~RemoteCameraHttp(); + RemoteCameraHttp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~RemoteCameraHttp(); - void Initialise(); - void Terminate() { Disconnect(); } - int Connect(); - int Disconnect(); - int SendRequest(); - int ReadData( Buffer &buffer, int bytes_expected=0 ); - int GetResponse(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + void Initialise(); + void Terminate() { Disconnect(); } + int Connect(); + int Disconnect(); + int SendRequest(); + int ReadData( Buffer &buffer, int bytes_expected=0 ); + int GetResponse(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); }; #endif // ZM_REMOTE_CAMERA_HTTP_H diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp index a07d97a8e..50c8ed3dc 100644 --- a/src/zm_remote_camera_rtsp.cpp +++ b/src/zm_remote_camera_rtsp.cpp @@ -29,343 +29,343 @@ #include RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : - RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ), - rtsp_describe( p_rtsp_describe ), - rtspThread( 0 ) + RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ), + rtsp_describe( p_rtsp_describe ), + rtspThread( 0 ) { - if ( p_method == "rtpUni" ) - method = RtspThread::RTP_UNICAST; - else if ( p_method == "rtpMulti" ) - method = RtspThread::RTP_MULTICAST; - else if ( p_method == "rtpRtsp" ) - method = RtspThread::RTP_RTSP; - else if ( p_method == "rtpRtspHttp" ) - method = RtspThread::RTP_RTSP_HTTP; - else - Fatal( "Unrecognised method '%s' when creating RTSP camera %d", p_method.c_str(), id ); + if ( p_method == "rtpUni" ) + method = RtspThread::RTP_UNICAST; + else if ( p_method == "rtpMulti" ) + method = RtspThread::RTP_MULTICAST; + else if ( p_method == "rtpRtsp" ) + method = RtspThread::RTP_RTSP; + else if ( p_method == "rtpRtspHttp" ) + method = RtspThread::RTP_RTSP_HTTP; + else + Fatal( "Unrecognised method '%s' when creating RTSP camera %d", p_method.c_str(), id ); - if ( capture ) - { - Initialise(); - } - - mFormatContext = NULL; - mVideoStreamId = -1; - mCodecContext = NULL; - mCodec = NULL; - mRawFrame = NULL; - mFrame = NULL; - frameCount = 0; - -#if HAVE_LIBSWSCALE - mConvertContext = NULL; + if ( capture ) + { + Initialise(); + } + + mFormatContext = NULL; + mVideoStreamId = -1; + mCodecContext = NULL; + mCodec = NULL; + mRawFrame = NULL; + mFrame = NULL; + frameCount = 0; + +#if HAVE_LIBSWSCALE + mConvertContext = NULL; #endif - /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ - if(colours == ZM_COLOUR_RGB32) { - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - imagePixFormat = AV_PIX_FMT_RGBA; - } else if(colours == ZM_COLOUR_RGB24) { - subpixelorder = ZM_SUBPIX_ORDER_RGB; - imagePixFormat = AV_PIX_FMT_RGB24; - } else if(colours == ZM_COLOUR_GRAY8) { - subpixelorder = ZM_SUBPIX_ORDER_NONE; - imagePixFormat = AV_PIX_FMT_GRAY8; - } else { - Panic("Unexpected colours: %d",colours); - } - + /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = AV_PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = AV_PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = AV_PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + } RemoteCameraRtsp::~RemoteCameraRtsp() { #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - av_frame_free( &mFrame ); - av_frame_free( &mRawFrame ); + av_frame_free( &mFrame ); + av_frame_free( &mRawFrame ); #else - av_freep( &mFrame ); - av_freep( &mRawFrame ); + av_freep( &mFrame ); + av_freep( &mRawFrame ); #endif - + #if HAVE_LIBSWSCALE - if ( mConvertContext ) - { - sws_freeContext( mConvertContext ); - mConvertContext = NULL; - } + if ( mConvertContext ) + { + sws_freeContext( mConvertContext ); + mConvertContext = NULL; + } #endif - if ( mCodecContext ) - { - avcodec_close( mCodecContext ); - mCodecContext = NULL; // Freed by avformat_free_context in the destructor of RtspThread class - } + if ( mCodecContext ) + { + avcodec_close( mCodecContext ); + mCodecContext = NULL; // Freed by avformat_free_context in the destructor of RtspThread class + } - if ( capture ) - { - Terminate(); - } + if ( capture ) + { + Terminate(); + } } void RemoteCameraRtsp::Initialise() { - RemoteCamera::Initialise(); + RemoteCamera::Initialise(); - int max_size = width*height*colours; + int max_size = width*height*colours; - buffer.size( max_size ); + buffer.size( max_size ); - if ( logDebugging() ) - av_log_set_level( AV_LOG_DEBUG ); - else - av_log_set_level( AV_LOG_QUIET ); + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); - av_register_all(); + av_register_all(); - Connect(); + Connect(); } void RemoteCameraRtsp::Terminate() { - Disconnect(); + Disconnect(); } int RemoteCameraRtsp::Connect() { - rtspThread = new RtspThread( id, method, protocol, host, port, path, auth, rtsp_describe ); + rtspThread = new RtspThread( id, method, protocol, host, port, path, auth, rtsp_describe ); - rtspThread->start(); + rtspThread->start(); - return( 0 ); + return( 0 ); } int RemoteCameraRtsp::Disconnect() { - if ( rtspThread ) - { - rtspThread->stop(); - rtspThread->join(); - delete rtspThread; - rtspThread = 0; - } - return( 0 ); + if ( rtspThread ) + { + rtspThread->stop(); + rtspThread->join(); + delete rtspThread; + rtspThread = 0; + } + return( 0 ); } int RemoteCameraRtsp::PrimeCapture() { - Debug( 2, "Waiting for sources" ); - for ( int i = 0; i < 100 && !rtspThread->hasSources(); i++ ) - { - usleep( 100000 ); - } - if ( !rtspThread->hasSources() ) - Fatal( "No RTSP sources" ); + Debug( 2, "Waiting for sources" ); + for ( int i = 0; i < 100 && !rtspThread->hasSources(); i++ ) + { + usleep( 100000 ); + } + if ( !rtspThread->hasSources() ) + Fatal( "No RTSP sources" ); - Debug( 2, "Got sources" ); + Debug( 2, "Got sources" ); - mFormatContext = rtspThread->getFormatContext(); + mFormatContext = rtspThread->getFormatContext(); - // Find first video stream present - mVideoStreamId = -1; - - for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) + // Find first video stream present + mVideoStreamId = -1; + + for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) + if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) #else - if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) + if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) #endif - { - mVideoStreamId = i; - break; - } - if ( mVideoStreamId == -1 ) - Fatal( "Unable to locate video stream" ); + { + mVideoStreamId = i; + break; + } + if ( mVideoStreamId == -1 ) + Fatal( "Unable to locate video stream" ); - // Get a pointer to the codec context for the video stream - mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; + // Get a pointer to the codec context for the video stream + mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; - // Find the decoder for the video stream - mCodec = avcodec_find_decoder( mCodecContext->codec_id ); - if ( mCodec == NULL ) - Panic( "Unable to locate codec %d decoder", mCodecContext->codec_id ); + // Find the decoder for the video stream + mCodec = avcodec_find_decoder( mCodecContext->codec_id ); + if ( mCodec == NULL ) + Panic( "Unable to locate codec %d decoder", mCodecContext->codec_id ); - // Open codec + // Open codec #if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0) - if ( avcodec_open( mCodecContext, mCodec ) < 0 ) + if ( avcodec_open( mCodecContext, mCodec ) < 0 ) #else - if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) + if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) #endif - Panic( "Can't open codec" ); + Panic( "Can't open codec" ); - // Allocate space for the native video frame + // Allocate space for the native video frame #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - mRawFrame = av_frame_alloc(); + mRawFrame = av_frame_alloc(); #else - mRawFrame = avcodec_alloc_frame(); + mRawFrame = avcodec_alloc_frame(); #endif - // Allocate space for the converted video frame + // Allocate space for the converted video frame #if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101) - mFrame = av_frame_alloc(); + mFrame = av_frame_alloc(); #else - mFrame = avcodec_alloc_frame(); + mFrame = avcodec_alloc_frame(); #endif - if(mRawFrame == NULL || mFrame == NULL) - Fatal( "Unable to allocate frame(s)"); - - int pSize = avpicture_get_size( imagePixFormat, width, height ); - if( (unsigned int)pSize != imagesize) { - Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); - } -/* + if(mRawFrame == NULL || mFrame == NULL) + Fatal( "Unable to allocate frame(s)"); + + int pSize = avpicture_get_size( imagePixFormat, width, height ); + if( (unsigned int)pSize != imagesize) { + Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); + } +/* #if HAVE_LIBSWSCALE - if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { - Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); - } + if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { + Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); + } - if(!sws_isSupportedOutput(imagePixFormat)) { - Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); - } - + if(!sws_isSupportedOutput(imagePixFormat)) { + Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); + } + #else // HAVE_LIBSWSCALE - Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); + Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); #endif // HAVE_LIBSWSCALE */ - return( 0 ); + return( 0 ); } int RemoteCameraRtsp::PreCapture() { - if ( !rtspThread->isRunning() ) - return( -1 ); - if ( !rtspThread->hasSources() ) - { - Error( "Cannot precapture, no RTP sources" ); - return( -1 ); - } - return( 0 ); + if ( !rtspThread->isRunning() ) + return( -1 ); + if ( !rtspThread->hasSources() ) + { + Error( "Cannot precapture, no RTP sources" ); + return( -1 ); + } + return( 0 ); } int RemoteCameraRtsp::Capture( Image &image ) { - AVPacket packet; - uint8_t* directbuffer; - int frameComplete = false; - - /* Request a writeable buffer of the target image */ - directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); - if(directbuffer == NULL) { - Error("Failed requesting writeable buffer for the captured image."); - return (-1); - } - - while ( true ) + AVPacket packet; + uint8_t* directbuffer; + int frameComplete = false; + + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } + + while ( true ) + { + buffer.clear(); + if ( !rtspThread->isRunning() ) + return (-1); + + if ( rtspThread->getFrame( buffer ) ) { - buffer.clear(); - if ( !rtspThread->isRunning() ) - return (-1); + Debug( 3, "Read frame %d bytes", buffer.size() ); + Debug( 4, "Address %p", buffer.head() ); + Hexdump( 4, buffer.head(), 16 ); - if ( rtspThread->getFrame( buffer ) ) + if ( !buffer.size() ) + return( -1 ); + + if(mCodecContext->codec_id == AV_CODEC_ID_H264) + { + // SPS and PPS frames should be saved and appended to IDR frames + int nalType = (buffer.head()[3] & 0x1f); + + // SPS + if(nalType == 7) { - Debug( 3, "Read frame %d bytes", buffer.size() ); - Debug( 4, "Address %p", buffer.head() ); - Hexdump( 4, buffer.head(), 16 ); + lastSps = buffer; + continue; + } + // PPS + else if(nalType == 8) + { + lastPps = buffer; + continue; + } + // IDR + else if(nalType == 5) + { + buffer += lastSps; + buffer += lastPps; + } + } - if ( !buffer.size() ) - return( -1 ); - - if(mCodecContext->codec_id == AV_CODEC_ID_H264) - { - // SPS and PPS frames should be saved and appended to IDR frames - int nalType = (buffer.head()[3] & 0x1f); - - // SPS - if(nalType == 7) - { - lastSps = buffer; - continue; - } - // PPS - else if(nalType == 8) - { - lastPps = buffer; - continue; - } - // IDR - else if(nalType == 5) - { - buffer += lastSps; - buffer += lastPps; - } - } - - av_init_packet( &packet ); - - while ( !frameComplete && buffer.size() > 0 ) - { - packet.data = buffer.head(); - packet.size = buffer.size(); + av_init_packet( &packet ); + + while ( !frameComplete && buffer.size() > 0 ) + { + packet.data = buffer.head(); + packet.size = buffer.size(); #if LIBAVCODEC_VERSION_CHECK(52, 23, 0, 23, 0) - int len = avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ); + int len = avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ); #else - int len = avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size ); + int len = avcodec_decode_video( mCodecContext, mRawFrame, &frameComplete, packet.data, packet.size ); #endif - if ( len < 0 ) - { - Error( "Error while decoding frame %d", frameCount ); - Hexdump( Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size() ); - buffer.clear(); - continue; - } - Debug( 2, "Frame: %d - %d/%d", frameCount, len, buffer.size() ); - //if ( buffer.size() < 400 ) - //Hexdump( 0, buffer.head(), buffer.size() ); - - buffer -= len; + if ( len < 0 ) + { + Error( "Error while decoding frame %d", frameCount ); + Hexdump( Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size() ); + buffer.clear(); + continue; + } + Debug( 2, "Frame: %d - %d/%d", frameCount, len, buffer.size() ); + //if ( buffer.size() < 400 ) + //Hexdump( 0, buffer.head(), buffer.size() ); + + buffer -= len; - } - if ( frameComplete ) { - - Debug( 3, "Got frame %d", frameCount ); - - avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); - -#if HAVE_LIBSWSCALE - if(mConvertContext == NULL) { - mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); - - if(mConvertContext == NULL) - Fatal( "Unable to create conversion context"); - } - - if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) - Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount ); -#else // HAVE_LIBSWSCALE - Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); -#endif // HAVE_LIBSWSCALE - - frameCount++; - - } /* frame complete */ - -#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) - av_packet_unref( &packet); -#else - av_free_packet( &packet ); -#endif - } /* getFrame() */ - - if(frameComplete) - return (0); - } - return (0) ; + if ( frameComplete ) { + + Debug( 3, "Got frame %d", frameCount ); + + avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); + +#if HAVE_LIBSWSCALE + if(mConvertContext == NULL) { + mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); + + if(mConvertContext == NULL) + Fatal( "Unable to create conversion context"); + } + + if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) + Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount ); +#else // HAVE_LIBSWSCALE + Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); +#endif // HAVE_LIBSWSCALE + + frameCount++; + + } /* frame complete */ + +#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100) + av_packet_unref( &packet); +#else + av_free_packet( &packet ); +#endif + } /* getFrame() */ + + if(frameComplete) + return (0); + + } + return (0) ; } int RemoteCameraRtsp::PostCapture() { - return( 0 ); + return( 0 ); } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_remote_camera_rtsp.h b/src/zm_remote_camera_rtsp.h index 420ac9cb2..20261f82d 100644 --- a/src/zm_remote_camera_rtsp.h +++ b/src/zm_remote_camera_rtsp.h @@ -35,50 +35,50 @@ class RemoteCameraRtsp : public RemoteCamera { protected: - struct sockaddr_in rtsp_sa; - struct sockaddr_in rtcp_sa; - int rtsp_sd; - int rtp_sd; - int rtcp_sd; - bool rtsp_describe; + struct sockaddr_in rtsp_sa; + struct sockaddr_in rtcp_sa; + int rtsp_sd; + int rtp_sd; + int rtcp_sd; + bool rtsp_describe; - Buffer buffer; - Buffer lastSps; - Buffer lastPps; + Buffer buffer; + Buffer lastSps; + Buffer lastPps; - RtspThread::RtspMethod method; + RtspThread::RtspMethod method; - RtspThread *rtspThread; + RtspThread *rtspThread; - int frameCount; - + int frameCount; + #if HAVE_LIBAVFORMAT - AVFormatContext *mFormatContext; - int mVideoStreamId; - AVCodecContext *mCodecContext; - AVCodec *mCodec; - AVFrame *mRawFrame; - AVFrame *mFrame; - _AVPIXELFORMAT imagePixFormat; + AVFormatContext *mFormatContext; + int mVideoStreamId; + AVCodecContext *mCodecContext; + AVCodec *mCodec; + AVFrame *mRawFrame; + AVFrame *mFrame; + _AVPIXELFORMAT imagePixFormat; #endif // HAVE_LIBAVFORMAT #if HAVE_LIBSWSCALE - struct SwsContext *mConvertContext; + struct SwsContext *mConvertContext; #endif public: - RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); - ~RemoteCameraRtsp(); + RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~RemoteCameraRtsp(); - void Initialise(); - void Terminate(); - int Connect(); - int Disconnect(); + void Initialise(); + void Terminate(); + int Connect(); + int Disconnect(); - int PrimeCapture(); - int PreCapture(); - int Capture( Image &image ); - int PostCapture(); + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); }; diff --git a/src/zm_rgb.h b/src/zm_rgb.h index bfef10501..af74d872b 100644 --- a/src/zm_rgb.h +++ b/src/zm_rgb.h @@ -20,80 +20,80 @@ #ifndef ZM_RGB_H #define ZM_RGB_H -typedef uint32_t Rgb; // RGB colour type +typedef uint32_t Rgb; // RGB colour type -#define WHITE 0xff -#define WHITE_R 0xff -#define WHITE_G 0xff -#define WHITE_B 0xff +#define WHITE 0xff +#define WHITE_R 0xff +#define WHITE_G 0xff +#define WHITE_B 0xff -#define BLACK 0x00 -#define BLACK_R 0x00 -#define BLACK_G 0x00 -#define BLACK_B 0x00 +#define BLACK 0x00 +#define BLACK_R 0x00 +#define BLACK_G 0x00 +#define BLACK_B 0x00 -#define RGB_WHITE (0x00ffffff) -#define RGB_BLACK (0x00000000) -#define RGB_RED (0x000000ff) -#define RGB_GREEN (0x0000ff00) -#define RGB_BLUE (0x00ff0000) -#define RGB_ORANGE (0x0000a5ff) -#define RGB_PURPLE (0x00800080) -#define RGB_TRANSPARENT (0x01000000) +#define RGB_WHITE (0x00ffffff) +#define RGB_BLACK (0x00000000) +#define RGB_RED (0x000000ff) +#define RGB_GREEN (0x0000ff00) +#define RGB_BLUE (0x00ff0000) +#define RGB_ORANGE (0x0000a5ff) +#define RGB_PURPLE (0x00800080) +#define RGB_TRANSPARENT (0x01000000) -#define RGB_VAL(v,c) (((v)>>(16-((c)*8)))&0xff) +#define RGB_VAL(v,c) (((v)>>(16-((c)*8)))&0xff) /* RGB or RGBA macros */ -#define BLUE_VAL_RGBA(v) (((v)>>16)&0xff) -#define GREEN_VAL_RGBA(v) (((v)>>8)&0xff) -#define RED_VAL_RGBA(v) ((v)&0xff) -#define ALPHA_VAL_RGBA(v) ((v)>>24)&0xff) -#define RED_PTR_RGBA(ptr) (*((uint8_t*)ptr)) -#define GREEN_PTR_RGBA(ptr) (*((uint8_t*)ptr+1)) -#define BLUE_PTR_RGBA(ptr) (*((uint8_t*)ptr+2)) -#define ALPHA_PTR_RGBA(ptr) (*((uint8_t*)ptr+3)) +#define BLUE_VAL_RGBA(v) (((v)>>16)&0xff) +#define GREEN_VAL_RGBA(v) (((v)>>8)&0xff) +#define RED_VAL_RGBA(v) ((v)&0xff) +#define ALPHA_VAL_RGBA(v) ((v)>>24)&0xff) +#define RED_PTR_RGBA(ptr) (*((uint8_t*)ptr)) +#define GREEN_PTR_RGBA(ptr) (*((uint8_t*)ptr+1)) +#define BLUE_PTR_RGBA(ptr) (*((uint8_t*)ptr+2)) +#define ALPHA_PTR_RGBA(ptr) (*((uint8_t*)ptr+3)) /* BGR or BGRA */ -#define RED_VAL_BGRA(v) (((v)>>16)&0xff) -#define GREEN_VAL_BGRA(v) (((v)>>8)&0xff) -#define BLUE_VAL_BGRA(v) ((v)&0xff) -#define ALPHA_VAL_BGRA(v) ((v)>>24)&0xff) -#define RED_PTR_BGRA(ptr) (*((uint8_t*)ptr+2)) -#define GREEN_PTR_BGRA(ptr) (*((uint8_t*)ptr+1)) -#define BLUE_PTR_BGRA(ptr) (*((uint8_t*)ptr)) -#define ALPHA_PTR_BGRA(ptr) (*((uint8_t*)ptr+3)) +#define RED_VAL_BGRA(v) (((v)>>16)&0xff) +#define GREEN_VAL_BGRA(v) (((v)>>8)&0xff) +#define BLUE_VAL_BGRA(v) ((v)&0xff) +#define ALPHA_VAL_BGRA(v) ((v)>>24)&0xff) +#define RED_PTR_BGRA(ptr) (*((uint8_t*)ptr+2)) +#define GREEN_PTR_BGRA(ptr) (*((uint8_t*)ptr+1)) +#define BLUE_PTR_BGRA(ptr) (*((uint8_t*)ptr)) +#define ALPHA_PTR_BGRA(ptr) (*((uint8_t*)ptr+3)) /* ARGB */ -#define BLUE_VAL_ARGB(v) (((v)>>24)&0xff) -#define GREEN_VAL_ARGB(v) (((v)>>16)&0xff) -#define RED_VAL_ARGB(v) (((v)>>8)&0xff) -#define ALPHA_VAL_ARGB(v) ((v)&0xff) -#define RED_PTR_ARGB(ptr) (*((uint8_t*)ptr+1)) -#define GREEN_PTR_ARGB(ptr) (*((uint8_t*)ptr+2)) -#define BLUE_PTR_ARGB(ptr) (*((uint8_t*)ptr+3)) -#define ALPHA_PTR_ARGB(ptr) (*((uint8_t*)ptr)) +#define BLUE_VAL_ARGB(v) (((v)>>24)&0xff) +#define GREEN_VAL_ARGB(v) (((v)>>16)&0xff) +#define RED_VAL_ARGB(v) (((v)>>8)&0xff) +#define ALPHA_VAL_ARGB(v) ((v)&0xff) +#define RED_PTR_ARGB(ptr) (*((uint8_t*)ptr+1)) +#define GREEN_PTR_ARGB(ptr) (*((uint8_t*)ptr+2)) +#define BLUE_PTR_ARGB(ptr) (*((uint8_t*)ptr+3)) +#define ALPHA_PTR_ARGB(ptr) (*((uint8_t*)ptr)) /* ABGR */ -#define BLUE_VAL_ABGR(v) (((v)>>8)&0xff) -#define GREEN_VAL_ABGR(v) (((v)>>16)&0xff) -#define RED_VAL_ABGR(v) (((v)>>24)&0xff) -#define ALPHA_VAL_ABGR(v) ((v)&0xff) -#define RED_PTR_ABGR(ptr) (*((uint8_t*)ptr+3)) -#define GREEN_PTR_ABGR(ptr) (*((uint8_t*)ptr+2)) -#define BLUE_PTR_ABGR(ptr) (*((uint8_t*)ptr+1)) -#define ALPHA_PTR_ABGR(ptr) (*((uint8_t*)ptr)) +#define BLUE_VAL_ABGR(v) (((v)>>8)&0xff) +#define GREEN_VAL_ABGR(v) (((v)>>16)&0xff) +#define RED_VAL_ABGR(v) (((v)>>24)&0xff) +#define ALPHA_VAL_ABGR(v) ((v)&0xff) +#define RED_PTR_ABGR(ptr) (*((uint8_t*)ptr+3)) +#define GREEN_PTR_ABGR(ptr) (*((uint8_t*)ptr+2)) +#define BLUE_PTR_ABGR(ptr) (*((uint8_t*)ptr+1)) +#define ALPHA_PTR_ABGR(ptr) (*((uint8_t*)ptr)) -#define RGBA_BGRA_ZEROALPHA(v) ((v)&0x00ffffff) -#define ARGB_ABGR_ZEROALPHA(v) ((v)&0xffffff00) +#define RGBA_BGRA_ZEROALPHA(v) ((v)&0x00ffffff) +#define ARGB_ABGR_ZEROALPHA(v) ((v)&0xffffff00) /* ITU-R BT.709: Y = (0.2126 * R) + (0.7152 * G) + (0.0722 * B) */ /* ITU-R BT.601: Y = (0.299 * R) + (0.587 * G) + (0.114 * B) */ /* The formulas below produce an almost identical result to the weighted algorithms from the ITU-R BT.601 standard and the newer ITU-R BT.709 standard, but a lot faster */ -// #define RGB_FASTLUM_SINGLE_ITU709(v) ((RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3) -// #define RGB_FASTLUM_VALUES_ITU709(ra,ga,ba) (((ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga)+(ga))>>3) -// #define RGB_FASTLUM_SINGLE_ITU601(v) ((RED(v)+RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3) -// #define RGB_FASTLUM_VALUES_ITU601(ra,ga,ba) (((ra)+(ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga))>>3) +// #define RGB_FASTLUM_SINGLE_ITU709(v) ((RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3) +// #define RGB_FASTLUM_VALUES_ITU709(ra,ga,ba) (((ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga)+(ga))>>3) +// #define RGB_FASTLUM_SINGLE_ITU601(v) ((RED(v)+RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3) +// #define RGB_FASTLUM_VALUES_ITU601(ra,ga,ba) (((ra)+(ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga))>>3) /* ZM colours */ #define ZM_COLOUR_RGB32 4 @@ -112,46 +112,46 @@ typedef uint32_t Rgb; // RGB colour type /* A macro to use default subpixel order for a specified colour. */ /* for grayscale it will use NONE, for 3 colours it will use R,G,B, for 4 colours it will use R,G,B,A */ -#define ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(c) ((c)<<1) +#define ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(c) ((c)<<1) /* Convert RGB colour value into BGR\ARGB\ABGR */ inline Rgb rgb_convert(Rgb p_col, int p_subpixorder) { - Rgb result; - - switch(p_subpixorder) { - - case ZM_SUBPIX_ORDER_BGR: - case ZM_SUBPIX_ORDER_BGRA: - { - BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col); - GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col); - RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col); - } - break; - case ZM_SUBPIX_ORDER_ARGB: - { - BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col); - GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col); - RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col); - } - break; - case ZM_SUBPIX_ORDER_ABGR: - { - BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col); - GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col); - RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col); - } - break; - /* Grayscale */ - case ZM_SUBPIX_ORDER_NONE: - result = p_col & 0xff; - break; - default: - return p_col; - break; - } - - return result; + Rgb result; + + switch(p_subpixorder) { + + case ZM_SUBPIX_ORDER_BGR: + case ZM_SUBPIX_ORDER_BGRA: + { + BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col); + } + break; + case ZM_SUBPIX_ORDER_ARGB: + { + BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col); + } + break; + case ZM_SUBPIX_ORDER_ABGR: + { + BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col); + } + break; + /* Grayscale */ + case ZM_SUBPIX_ORDER_NONE: + result = p_col & 0xff; + break; + default: + return p_col; + break; + } + + return result; } #endif // ZM_RGB_H diff --git a/src/zm_rtp_ctrl.cpp b/src/zm_rtp_ctrl.cpp index 1a0604137..5ff23b31d 100644 --- a/src/zm_rtp_ctrl.cpp +++ b/src/zm_rtp_ctrl.cpp @@ -34,343 +34,343 @@ RtpCtrlThread::RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ) : m int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) { - const RtcpPacket *rtcpPacket; - rtcpPacket = (RtcpPacket *)packet; + const RtcpPacket *rtcpPacket; + rtcpPacket = (RtcpPacket *)packet; - int consumed = 0; + int consumed = 0; - //printf( "C: " ); - //for ( int i = 0; i < packetLen; i++ ) - //printf( "%02x ", (unsigned char)packet[i] ); - //printf( "\n" ); - int ver = rtcpPacket->header.version; - int count = rtcpPacket->header.count; - int pt = rtcpPacket->header.pt; - int len = ntohs(rtcpPacket->header.lenN); + //printf( "C: " ); + //for ( int i = 0; i < packetLen; i++ ) + //printf( "%02x ", (unsigned char)packet[i] ); + //printf( "\n" ); + int ver = rtcpPacket->header.version; + int count = rtcpPacket->header.count; + int pt = rtcpPacket->header.pt; + int len = ntohs(rtcpPacket->header.lenN); - Debug( 5, "RTCP Ver: %d", ver ); - Debug( 5, "RTCP Count: %d", count ); - Debug( 5, "RTCP Pt: %d", pt ); - Debug( 5, "RTCP len: %d", len ); + Debug( 5, "RTCP Ver: %d", ver ); + Debug( 5, "RTCP Count: %d", count ); + Debug( 5, "RTCP Pt: %d", pt ); + Debug( 5, "RTCP len: %d", len ); - switch( pt ) + switch( pt ) + { + case RTCP_SR : { - case RTCP_SR : - { - uint32_t ssrc = ntohl(rtcpPacket->body.sr.ssrcN); + uint32_t ssrc = ntohl(rtcpPacket->body.sr.ssrcN); - Debug( 5, "RTCP Got SR (%x)", ssrc ); - if ( mRtpSource.getSsrc() ) - { - if ( ssrc != mRtpSource.getSsrc() ) - { - Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); - return( -1 ); - } - } - else if ( ssrc ) - { - mRtpSource.setSsrc( ssrc ); - } + Debug( 5, "RTCP Got SR (%x)", ssrc ); + if ( mRtpSource.getSsrc() ) + { + if ( ssrc != mRtpSource.getSsrc() ) + { + Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); + return( -1 ); + } + } + else if ( ssrc ) + { + mRtpSource.setSsrc( ssrc ); + } - if ( len > 1 ) - { - //printf( "NTPts:%d.%d, RTPts:%d\n", $ntptsmsb, $ntptslsb, $rtpts ); - uint16_t ntptsmsb = ntohl(rtcpPacket->body.sr.ntpSecN); - uint16_t ntptslsb = ntohl(rtcpPacket->body.sr.ntpFracN); - //printf( "NTPts:%x.%04x, RTPts:%x\n", $ntptsmsb, $ntptslsb, $rtpts ); - //printf( "Pkts:$sendpkts, Octs:$sendocts\n" ); - uint32_t rtpTime = ntohl(rtcpPacket->body.sr.rtpTsN); + if ( len > 1 ) + { + //printf( "NTPts:%d.%d, RTPts:%d\n", $ntptsmsb, $ntptslsb, $rtpts ); + uint16_t ntptsmsb = ntohl(rtcpPacket->body.sr.ntpSecN); + uint16_t ntptslsb = ntohl(rtcpPacket->body.sr.ntpFracN); + //printf( "NTPts:%x.%04x, RTPts:%x\n", $ntptsmsb, $ntptslsb, $rtpts ); + //printf( "Pkts:$sendpkts, Octs:$sendocts\n" ); + uint32_t rtpTime = ntohl(rtcpPacket->body.sr.rtpTsN); - mRtpSource.updateRtcpData( ntptsmsb, ntptslsb, rtpTime ); - } - break; - } - case RTCP_SDES : - { - ssize_t contentLen = packetLen - sizeof(rtcpPacket->header); - while ( contentLen ) - { - Debug( 5, "RTCP CL: %zd", contentLen ); - uint32_t ssrc = ntohl(rtcpPacket->body.sdes.srcN); - - Debug( 5, "RTCP Got SDES (%x), %d items", ssrc, count ); - if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) - { - Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); - return( -1 ); - } - - unsigned char *sdesPtr = (unsigned char *)&rtcpPacket->body.sdes.item; - for ( int i = 0; i < count; i++ ) - { - RtcpSdesItem *item = (RtcpSdesItem *)sdesPtr; - Debug( 5, "RTCP Item length %d", item->len ); - switch( item->type ) - { - case RTCP_SDES_CNAME : - { - std::string cname( item->data, item->len ); - Debug( 5, "RTCP Got CNAME %s", cname.c_str() ); - break; - } - case RTCP_SDES_END : - case RTCP_SDES_NAME : - case RTCP_SDES_EMAIL : - case RTCP_SDES_PHONE : - case RTCP_SDES_LOC : - case RTCP_SDES_TOOL : - case RTCP_SDES_NOTE : - case RTCP_SDES_PRIV : - default : - { - Error( "Received unexpected SDES item type %d, ignoring", item->type ); - return( -1 ); - } - } - int paddedLen = 4+2+item->len+1; // Add null byte - paddedLen = (((paddedLen-1)/4)+1)*4; // Round to nearest multiple of 4 - Debug( 5, "RTCP PL:%d", paddedLen ); - sdesPtr += paddedLen; - contentLen = ( paddedLen <= contentLen ) ? ( contentLen - paddedLen ) : 0; - } - } - break; - } - case RTCP_BYE : - { - Debug( 5, "RTCP Got BYE" ); - mStop = true; - break; - } - case RTCP_APP : - { - // Ignoring as per RFC 3550 - Debug( 5, "Received RTCP_APP packet, ignoring."); - break; - } - case RTCP_RR : - { - Error( "Received RTCP_RR packet." ); - return( -1 ); - } - default : - { - // Ignore unknown packet types. Some cameras do this by design. - Debug( 5, "Received unexpected packet type %d, ignoring", pt ); - break; - } + mRtpSource.updateRtcpData( ntptsmsb, ntptslsb, rtpTime ); + } + break; } - consumed = sizeof(uint32_t)*(len+1); - return( consumed ); + case RTCP_SDES : + { + ssize_t contentLen = packetLen - sizeof(rtcpPacket->header); + while ( contentLen ) + { + Debug( 5, "RTCP CL: %zd", contentLen ); + uint32_t ssrc = ntohl(rtcpPacket->body.sdes.srcN); + + Debug( 5, "RTCP Got SDES (%x), %d items", ssrc, count ); + if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) + { + Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); + return( -1 ); + } + + unsigned char *sdesPtr = (unsigned char *)&rtcpPacket->body.sdes.item; + for ( int i = 0; i < count; i++ ) + { + RtcpSdesItem *item = (RtcpSdesItem *)sdesPtr; + Debug( 5, "RTCP Item length %d", item->len ); + switch( item->type ) + { + case RTCP_SDES_CNAME : + { + std::string cname( item->data, item->len ); + Debug( 5, "RTCP Got CNAME %s", cname.c_str() ); + break; + } + case RTCP_SDES_END : + case RTCP_SDES_NAME : + case RTCP_SDES_EMAIL : + case RTCP_SDES_PHONE : + case RTCP_SDES_LOC : + case RTCP_SDES_TOOL : + case RTCP_SDES_NOTE : + case RTCP_SDES_PRIV : + default : + { + Error( "Received unexpected SDES item type %d, ignoring", item->type ); + return( -1 ); + } + } + int paddedLen = 4+2+item->len+1; // Add null byte + paddedLen = (((paddedLen-1)/4)+1)*4; // Round to nearest multiple of 4 + Debug( 5, "RTCP PL:%d", paddedLen ); + sdesPtr += paddedLen; + contentLen = ( paddedLen <= contentLen ) ? ( contentLen - paddedLen ) : 0; + } + } + break; + } + case RTCP_BYE : + { + Debug( 5, "RTCP Got BYE" ); + mStop = true; + break; + } + case RTCP_APP : + { + // Ignoring as per RFC 3550 + Debug( 5, "Received RTCP_APP packet, ignoring."); + break; + } + case RTCP_RR : + { + Error( "Received RTCP_RR packet." ); + return( -1 ); + } + default : + { + // Ignore unknown packet types. Some cameras do this by design. + Debug( 5, "Received unexpected packet type %d, ignoring", pt ); + break; + } + } + consumed = sizeof(uint32_t)*(len+1); + return( consumed ); } int RtpCtrlThread::generateRr( const unsigned char *packet, ssize_t packetLen ) { - RtcpPacket *rtcpPacket = (RtcpPacket *)packet; + RtcpPacket *rtcpPacket = (RtcpPacket *)packet; - int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.rr)+sizeof(rtcpPacket->body.rr.rr[0]); - int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; + int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.rr)+sizeof(rtcpPacket->body.rr.rr[0]); + int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; - rtcpPacket->header.version = RTP_VERSION; - rtcpPacket->header.p = 0; - rtcpPacket->header.pt = RTCP_RR; - rtcpPacket->header.count = 1; - rtcpPacket->header.lenN = htons(wordLen-1); + rtcpPacket->header.version = RTP_VERSION; + rtcpPacket->header.p = 0; + rtcpPacket->header.pt = RTCP_RR; + rtcpPacket->header.count = 1; + rtcpPacket->header.lenN = htons(wordLen-1); - mRtpSource.updateRtcpStats(); + mRtpSource.updateRtcpStats(); - Debug( 5, "Ssrc = %d", mRtspThread.getSsrc()+1 ); - Debug( 5, "Ssrc_1 = %d", mRtpSource.getSsrc() ); - Debug( 5, "Last Seq = %d", mRtpSource.getMaxSeq() ); - Debug( 5, "Jitter = %d", mRtpSource.getJitter() ); - Debug( 5, "Last SR = %d", mRtpSource.getLastSrTimestamp() ); + Debug( 5, "Ssrc = %d", mRtspThread.getSsrc()+1 ); + Debug( 5, "Ssrc_1 = %d", mRtpSource.getSsrc() ); + Debug( 5, "Last Seq = %d", mRtpSource.getMaxSeq() ); + Debug( 5, "Jitter = %d", mRtpSource.getJitter() ); + Debug( 5, "Last SR = %d", mRtpSource.getLastSrTimestamp() ); - rtcpPacket->body.rr.ssrcN = htonl(mRtspThread.getSsrc()+1); - rtcpPacket->body.rr.rr[0].ssrcN = htonl(mRtpSource.getSsrc()); - rtcpPacket->body.rr.rr[0].lost = mRtpSource.getLostPackets(); - rtcpPacket->body.rr.rr[0].fraction = mRtpSource.getLostFraction(); - rtcpPacket->body.rr.rr[0].lastSeqN = htonl(mRtpSource.getMaxSeq()); - rtcpPacket->body.rr.rr[0].jitterN = htonl(mRtpSource.getJitter()); - rtcpPacket->body.rr.rr[0].lsrN = htonl(mRtpSource.getLastSrTimestamp()); - rtcpPacket->body.rr.rr[0].dlsrN = 0; + rtcpPacket->body.rr.ssrcN = htonl(mRtspThread.getSsrc()+1); + rtcpPacket->body.rr.rr[0].ssrcN = htonl(mRtpSource.getSsrc()); + rtcpPacket->body.rr.rr[0].lost = mRtpSource.getLostPackets(); + rtcpPacket->body.rr.rr[0].fraction = mRtpSource.getLostFraction(); + rtcpPacket->body.rr.rr[0].lastSeqN = htonl(mRtpSource.getMaxSeq()); + rtcpPacket->body.rr.rr[0].jitterN = htonl(mRtpSource.getJitter()); + rtcpPacket->body.rr.rr[0].lsrN = htonl(mRtpSource.getLastSrTimestamp()); + rtcpPacket->body.rr.rr[0].dlsrN = 0; - return( wordLen*sizeof(uint32_t) ); + return( wordLen*sizeof(uint32_t) ); } int RtpCtrlThread::generateSdes( const unsigned char *packet, ssize_t packetLen ) { - RtcpPacket *rtcpPacket = (RtcpPacket *)packet; + RtcpPacket *rtcpPacket = (RtcpPacket *)packet; - const std::string &cname = mRtpSource.getCname(); + const std::string &cname = mRtpSource.getCname(); - int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.sdes)+sizeof(rtcpPacket->body.sdes.item[0])+cname.size(); - int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; + int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.sdes)+sizeof(rtcpPacket->body.sdes.item[0])+cname.size(); + int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; - rtcpPacket->header.version = RTP_VERSION; - rtcpPacket->header.p = 0; - rtcpPacket->header.pt = RTCP_SDES; - rtcpPacket->header.count = 1; - rtcpPacket->header.lenN = htons(wordLen-1); + rtcpPacket->header.version = RTP_VERSION; + rtcpPacket->header.p = 0; + rtcpPacket->header.pt = RTCP_SDES; + rtcpPacket->header.count = 1; + rtcpPacket->header.lenN = htons(wordLen-1); - rtcpPacket->body.sdes.srcN = htonl(mRtpSource.getSsrc()+1); - rtcpPacket->body.sdes.item[0].type = RTCP_SDES_CNAME; - rtcpPacket->body.sdes.item[0].len = cname.size(); - memcpy( rtcpPacket->body.sdes.item[0].data, cname.data(), cname.size() ); + rtcpPacket->body.sdes.srcN = htonl(mRtpSource.getSsrc()+1); + rtcpPacket->body.sdes.item[0].type = RTCP_SDES_CNAME; + rtcpPacket->body.sdes.item[0].len = cname.size(); + memcpy( rtcpPacket->body.sdes.item[0].data, cname.data(), cname.size() ); - return( wordLen*sizeof(uint32_t) ); + return( wordLen*sizeof(uint32_t) ); } int RtpCtrlThread::generateBye( const unsigned char *packet, ssize_t packetLen ) { - RtcpPacket *rtcpPacket = (RtcpPacket *)packet; + RtcpPacket *rtcpPacket = (RtcpPacket *)packet; - int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.bye)+sizeof(rtcpPacket->body.bye.srcN[0]); - int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; + int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.bye)+sizeof(rtcpPacket->body.bye.srcN[0]); + int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; - rtcpPacket->header.version = RTP_VERSION; - rtcpPacket->header.p = 0; - rtcpPacket->header.pt = RTCP_BYE; - rtcpPacket->header.count = 1; - rtcpPacket->header.lenN = htons(wordLen-1); + rtcpPacket->header.version = RTP_VERSION; + rtcpPacket->header.p = 0; + rtcpPacket->header.pt = RTCP_BYE; + rtcpPacket->header.count = 1; + rtcpPacket->header.lenN = htons(wordLen-1); - rtcpPacket->body.bye.srcN[0] = htonl(mRtpSource.getSsrc()); + rtcpPacket->body.bye.srcN[0] = htonl(mRtpSource.getSsrc()); - return( wordLen*sizeof(uint32_t) ); + return( wordLen*sizeof(uint32_t) ); } int RtpCtrlThread::recvPackets( unsigned char *buffer, ssize_t nBytes ) { - unsigned char *bufferPtr = buffer; + unsigned char *bufferPtr = buffer; - // u_int32 len; /* length of compound RTCP packet in words */ - // rtcp_t *r; /* RTCP header */ - // rtcp_t *end; /* end of compound RTCP packet */ + // u_int32 len; /* length of compound RTCP packet in words */ + // rtcp_t *r; /* RTCP header */ + // rtcp_t *end; /* end of compound RTCP packet */ - // if ((*(u_int16 *)r & RTCP_VALID_MASK) != RTCP_VALID_VALUE) { - // /* something wrong with packet format */ - // } - // end = (rtcp_t *)((u_int32 *)r + len); + // if ((*(u_int16 *)r & RTCP_VALID_MASK) != RTCP_VALID_VALUE) { + // /* something wrong with packet format */ + // } + // end = (rtcp_t *)((u_int32 *)r + len); - // do r = (rtcp_t *)((u_int32 *)r + r->common.length + 1); - // while (r < end && r->common.version == 2); + // do r = (rtcp_t *)((u_int32 *)r + r->common.length + 1); + // while (r < end && r->common.version == 2); - // if (r != end) { - // /* something wrong with packet format */ - // } + // if (r != end) { + // /* something wrong with packet format */ + // } - while ( nBytes > 0 ) - { - int consumed = recvPacket( bufferPtr, nBytes ); - if ( consumed <= 0 ) - break; - bufferPtr += consumed; - nBytes -= consumed; - } - return( nBytes ); + while ( nBytes > 0 ) + { + int consumed = recvPacket( bufferPtr, nBytes ); + if ( consumed <= 0 ) + break; + bufferPtr += consumed; + nBytes -= consumed; + } + return( nBytes ); } int RtpCtrlThread::run() { - Debug( 2, "Starting control thread %x on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalCtrlPort() ); - SockAddrInet localAddr, remoteAddr; + Debug( 2, "Starting control thread %x on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalCtrlPort() ); + SockAddrInet localAddr, remoteAddr; - bool sendReports; - UdpInetSocket rtpCtrlServer; - if ( mRtpSource.getLocalHost() != "" ) + bool sendReports; + UdpInetSocket rtpCtrlServer; + if ( mRtpSource.getLocalHost() != "" ) + { + localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort(), "udp" ); + if ( !rtpCtrlServer.bind( localAddr ) ) + Fatal( "Failed to bind RTCP server" ); + sendReports = false; + Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); + } + else + { + localAddr.resolve( mRtpSource.getLocalCtrlPort(), "udp" ); + if ( !rtpCtrlServer.bind( localAddr ) ) + Fatal( "Failed to bind RTCP server" ); + Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); + remoteAddr.resolve( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort(), "udp" ); + if ( !rtpCtrlServer.connect( remoteAddr ) ) + Fatal( "Failed to connect RTCP server" ); + Debug( 3, "Connected to %s:%d", mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ); + sendReports = true; + } + + // The only reason I can think of why we would have a timeout period is so that we can regularly send RR packets. + // Why 10 seconds? If anything I think this should be whatever timeout value was given in the DESCRIBE response + Select select( 10 ); + select.addReader( &rtpCtrlServer ); + + unsigned char buffer[ZM_NETWORK_BUFSIZ]; + + time_t last_receive = time(NULL); + bool timeout = false; // used as a flag that we had a timeout, and then sent an RR to see if we wake back up. Real timeout will happen when this is true. + + while ( !mStop && select.wait() >= 0 ) { + + time_t now = time(NULL); + Select::CommsList readable = select.getReadable(); + if ( readable.size() == 0 ) { - localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort(), "udp" ); - if ( !rtpCtrlServer.bind( localAddr ) ) - Fatal( "Failed to bind RTCP server" ); - sendReports = false; - Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); + if ( ! timeout ) { + // With this code here, we will send an SDES and RR packet every 10 seconds + ssize_t nBytes; + unsigned char *bufferPtr = buffer; + bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); + bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); + Debug( 3, "Preventing timeout by sending %zd bytes on sd %d. Time since last receive: %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc(), ( now-last_receive) ); + if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) + Error( "Unable to send: %s", strerror( errno ) ); + timeout = true; + continue; + } else { + //Error( "RTCP timed out" ); + Debug(1, "RTCP timed out. Time since last receive: %d", ( now-last_receive) ); + continue; + //break; + } + } else { + timeout = false; + last_receive = time(NULL); } - else + for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) { - localAddr.resolve( mRtpSource.getLocalCtrlPort(), "udp" ); - if ( !rtpCtrlServer.bind( localAddr ) ) - Fatal( "Failed to bind RTCP server" ); - Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); - remoteAddr.resolve( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort(), "udp" ); - if ( !rtpCtrlServer.connect( remoteAddr ) ) - Fatal( "Failed to connect RTCP server" ); - Debug( 3, "Connected to %s:%d", mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ); - sendReports = true; - } + if ( UdpInetSocket *socket = dynamic_cast(*iter) ) + { + ssize_t nBytes = socket->recv( buffer, sizeof(buffer) ); + Debug( 4, "Read %zd bytes on sd %d", nBytes, socket->getReadDesc() ); - // The only reason I can think of why we would have a timeout period is so that we can regularly send RR packets. - // Why 10 seconds? If anything I think this should be whatever timeout value was given in the DESCRIBE response - Select select( 10 ); - select.addReader( &rtpCtrlServer ); - - unsigned char buffer[ZM_NETWORK_BUFSIZ]; - - time_t last_receive = time(NULL); - bool timeout = false; // used as a flag that we had a timeout, and then sent an RR to see if we wake back up. Real timeout will happen when this is true. - - while ( !mStop && select.wait() >= 0 ) { - - time_t now = time(NULL); - Select::CommsList readable = select.getReadable(); - if ( readable.size() == 0 ) + if ( nBytes ) { - if ( ! timeout ) { - // With this code here, we will send an SDES and RR packet every 10 seconds - ssize_t nBytes; - unsigned char *bufferPtr = buffer; - bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); - bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); - Debug( 3, "Preventing timeout by sending %zd bytes on sd %d. Time since last receive: %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc(), ( now-last_receive) ); - if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) - Error( "Unable to send: %s", strerror( errno ) ); - timeout = true; - continue; - } else { - //Error( "RTCP timed out" ); - Debug(1, "RTCP timed out. Time since last receive: %d", ( now-last_receive) ); - continue; - //break; - } - } else { - timeout = false; - last_receive = time(NULL); - } - for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) - { - if ( UdpInetSocket *socket = dynamic_cast(*iter) ) - { - ssize_t nBytes = socket->recv( buffer, sizeof(buffer) ); - Debug( 4, "Read %zd bytes on sd %d", nBytes, socket->getReadDesc() ); + recvPackets( buffer, nBytes ); - if ( nBytes ) - { - recvPackets( buffer, nBytes ); - - if ( sendReports ) - { - unsigned char *bufferPtr = buffer; - bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); - bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); - Debug( 3, "Sending %zd bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc() ); - if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) - Error( "Unable to send: %s", strerror( errno ) ); - //Debug( 4, "Sent %d bytes on sd %d", nBytes, rtpCtrlServer.getWriteDesc() ); - } - } else { - // Here is another case of not receiving some data causing us to terminate... why? Sometimes there are pauses in the interwebs. - mStop = true; - break; - } - } - else - { - Panic( "Barfed" ); - } + if ( sendReports ) + { + unsigned char *bufferPtr = buffer; + bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); + bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); + Debug( 3, "Sending %zd bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc() ); + if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) + Error( "Unable to send: %s", strerror( errno ) ); + //Debug( 4, "Sent %d bytes on sd %d", nBytes, rtpCtrlServer.getWriteDesc() ); + } + } else { + // Here is another case of not receiving some data causing us to terminate... why? Sometimes there are pauses in the interwebs. + mStop = true; + break; } + } + else + { + Panic( "Barfed" ); + } } - rtpCtrlServer.close(); - mRtspThread.stop(); - return( 0 ); + } + rtpCtrlServer.close(); + mRtspThread.stop(); + return( 0 ); } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtp_ctrl.h b/src/zm_rtp_ctrl.h index 9b44b752b..2526f22ce 100644 --- a/src/zm_rtp_ctrl.h +++ b/src/zm_rtp_ctrl.h @@ -25,7 +25,7 @@ #include "zm_thread.h" // Defined in ffmpeg rtp.h -//#define RTP_MAX_SDES 255 // maximum text length for SDES +//#define RTP_MAX_SDES 255 // maximum text length for SDES // Big-endian mask for version, padding bit and packet type pair #define RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe) @@ -39,119 +39,119 @@ class RtpCtrlThread : public Thread friend class RtspThread; private: - typedef enum + typedef enum + { + RTCP_SR = 200, + RTCP_RR = 201, + RTCP_SDES = 202, + RTCP_BYE = 203, + RTCP_APP = 204 + } RtcpType; + + typedef enum + { + RTCP_SDES_END = 0, + RTCP_SDES_CNAME = 1, + RTCP_SDES_NAME = 2, + RTCP_SDES_EMAIL = 3, + RTCP_SDES_PHONE = 4, + RTCP_SDES_LOC = 5, + RTCP_SDES_TOOL = 6, + RTCP_SDES_NOTE = 7, + RTCP_SDES_PRIV = 8 + } RtcpSdesType; + + struct RtcpCommonHeader + { + uint8_t count:5; // varies by packet type + uint8_t p:1; // padding flag + uint8_t version:2; // protocol version + uint8_t pt; // RTCP packet type + uint16_t lenN; // pkt len in words, w/o this word, network order + }; + + // Reception report block + struct RtcpRr + { + uint32_t ssrcN; // data source being reported + int32_t lost:24; // cumul. no. pkts lost (signed!) + uint32_t fraction:8; // fraction lost since last SR/RR + uint32_t lastSeqN; // extended last seq. no. received, network order + uint32_t jitterN; // interarrival jitter, network order + uint32_t lsrN; // last SR packet from this source, network order + uint32_t dlsrN; // delay since last SR packet, network order + }; + + // SDES item + struct RtcpSdesItem + { + uint8_t type; // type of item (rtcp_sdes_type_t) + uint8_t len; // length of item (in octets) + char data[]; // text, not null-terminated + }; + + // RTCP packet + struct RtcpPacket + { + RtcpCommonHeader header; // common header + union { - RTCP_SR = 200, - RTCP_RR = 201, - RTCP_SDES = 202, - RTCP_BYE = 203, - RTCP_APP = 204 - } RtcpType; + // Sender Report (SR) + struct Sr + { + uint32_t ssrcN; // sender generating this report, network order + uint32_t ntpSecN; // NTP timestamp, network order + uint32_t ntpFracN; + uint32_t rtpTsN; // RTP timestamp, network order + uint32_t pSentN; // packets sent, network order + uint32_t oSentN; // octets sent, network order + RtcpRr rr[]; // variable-length list + } sr; - typedef enum - { - RTCP_SDES_END = 0, - RTCP_SDES_CNAME = 1, - RTCP_SDES_NAME = 2, - RTCP_SDES_EMAIL = 3, - RTCP_SDES_PHONE = 4, - RTCP_SDES_LOC = 5, - RTCP_SDES_TOOL = 6, - RTCP_SDES_NOTE = 7, - RTCP_SDES_PRIV = 8 - } RtcpSdesType; + // Reception Report (RR) + struct Rr + { + uint32_t ssrcN; // receiver generating this report + RtcpRr rr[]; // variable-length list + } rr; - struct RtcpCommonHeader - { - uint8_t count:5; // varies by packet type - uint8_t p:1; // padding flag - uint8_t version:2; // protocol version - uint8_t pt; // RTCP packet type - uint16_t lenN; // pkt len in words, w/o this word, network order - }; + // source description (SDES) + struct Sdes + { + uint32_t srcN; // first SSRC/CSRC + RtcpSdesItem item[]; // list of SDES items + } sdes; - // Reception report block - struct RtcpRr - { - uint32_t ssrcN; // data source being reported - int32_t lost:24; // cumul. no. pkts lost (signed!) - uint32_t fraction:8; // fraction lost since last SR/RR - uint32_t lastSeqN; // extended last seq. no. received, network order - uint32_t jitterN; // interarrival jitter, network order - uint32_t lsrN; // last SR packet from this source, network order - uint32_t dlsrN; // delay since last SR packet, network order - }; - - // SDES item - struct RtcpSdesItem - { - uint8_t type; // type of item (rtcp_sdes_type_t) - uint8_t len; // length of item (in octets) - char data[]; // text, not null-terminated - }; - - // RTCP packet - struct RtcpPacket - { - RtcpCommonHeader header; // common header - union - { - // Sender Report (SR) - struct Sr - { - uint32_t ssrcN; // sender generating this report, network order - uint32_t ntpSecN; // NTP timestamp, network order - uint32_t ntpFracN; - uint32_t rtpTsN; // RTP timestamp, network order - uint32_t pSentN; // packets sent, network order - uint32_t oSentN; // octets sent, network order - RtcpRr rr[]; // variable-length list - } sr; - - // Reception Report (RR) - struct Rr - { - uint32_t ssrcN; // receiver generating this report - RtcpRr rr[]; // variable-length list - } rr; - - // source description (SDES) - struct Sdes - { - uint32_t srcN; // first SSRC/CSRC - RtcpSdesItem item[]; // list of SDES items - } sdes; - - // BYE - struct Bye - { - uint32_t srcN[]; // list of sources - // can't express trailing text for reason (what does this mean? it's not even english!) - } bye; - } body; - }; + // BYE + struct Bye + { + uint32_t srcN[]; // list of sources + // can't express trailing text for reason (what does this mean? it's not even english!) + } bye; + } body; + }; private: - RtspThread &mRtspThread; - RtpSource &mRtpSource; - int mPort; - bool mStop; + RtspThread &mRtspThread; + RtpSource &mRtpSource; + int mPort; + bool mStop; private: - int recvPacket( const unsigned char *packet, ssize_t packetLen ); - int generateRr( const unsigned char *packet, ssize_t packetLen ); - int generateSdes( const unsigned char *packet, ssize_t packetLen ); - int generateBye( const unsigned char *packet, ssize_t packetLen ); - int recvPackets( unsigned char *buffer, ssize_t nBytes ); - int run(); + int recvPacket( const unsigned char *packet, ssize_t packetLen ); + int generateRr( const unsigned char *packet, ssize_t packetLen ); + int generateSdes( const unsigned char *packet, ssize_t packetLen ); + int generateBye( const unsigned char *packet, ssize_t packetLen ); + int recvPackets( unsigned char *buffer, ssize_t nBytes ); + int run(); public: - RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ); + RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ); - void stop() - { - mStop = true; - } + void stop() + { + mStop = true; + } }; #endif // ZM_RTP_CTRL_H diff --git a/src/zm_rtp_data.cpp b/src/zm_rtp_data.cpp index 257f46947..687a4995e 100644 --- a/src/zm_rtp_data.cpp +++ b/src/zm_rtp_data.cpp @@ -33,88 +33,88 @@ RtpDataThread::RtpDataThread( RtspThread &rtspThread, RtpSource &rtpSource ) : m bool RtpDataThread::recvPacket( const unsigned char *packet, size_t packetLen ) { - const RtpDataHeader *rtpHeader; - rtpHeader = (RtpDataHeader *)packet; + const RtpDataHeader *rtpHeader; + rtpHeader = (RtpDataHeader *)packet; - //printf( "D: " ); - //for ( int i = 0; i < 32; i++ ) - //printf( "%02x ", (unsigned char)packet[i] ); - //printf( "\n" ); + //printf( "D: " ); + //for ( int i = 0; i < 32; i++ ) + //printf( "%02x ", (unsigned char)packet[i] ); + //printf( "\n" ); - Debug( 5, "Ver: %d", rtpHeader->version ); - Debug( 5, "P: %d", rtpHeader->p ); - Debug( 5, "Pt: %d", rtpHeader->pt ); - Debug( 5, "Mk: %d", rtpHeader->m ); - Debug( 5, "Seq: %d", ntohs(rtpHeader->seqN) ); - Debug( 5, "T/S: %x", ntohl(rtpHeader->timestampN) ); - Debug( 5, "SSRC: %x", ntohl(rtpHeader->ssrcN) ); + Debug( 5, "Ver: %d", rtpHeader->version ); + Debug( 5, "P: %d", rtpHeader->p ); + Debug( 5, "Pt: %d", rtpHeader->pt ); + Debug( 5, "Mk: %d", rtpHeader->m ); + Debug( 5, "Seq: %d", ntohs(rtpHeader->seqN) ); + Debug( 5, "T/S: %x", ntohl(rtpHeader->timestampN) ); + Debug( 5, "SSRC: %x", ntohl(rtpHeader->ssrcN) ); - //unsigned short seq = ntohs(rtpHeader->seqN); - unsigned long ssrc = ntohl(rtpHeader->ssrcN); + //unsigned short seq = ntohs(rtpHeader->seqN); + unsigned long ssrc = ntohl(rtpHeader->ssrcN); - if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) - { - Warning( "Discarding packet for unrecognised ssrc %lx", ssrc ); - return( false ); - } + if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) + { + Warning( "Discarding packet for unrecognised ssrc %lx", ssrc ); + return( false ); + } - return( mRtpSource.handlePacket( packet, packetLen ) ); + return( mRtpSource.handlePacket( packet, packetLen ) ); } int RtpDataThread::run() { - Debug( 2, "Starting data thread %d on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalDataPort() ); + Debug( 2, "Starting data thread %d on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalDataPort() ); - SockAddrInet localAddr; - UdpInetServer rtpDataSocket; - if ( mRtpSource.getLocalHost() != "" ) - localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort(), "udp" ); - else - localAddr.resolve( mRtpSource.getLocalDataPort(), "udp" ); - if ( !rtpDataSocket.bind( localAddr ) ) - Fatal( "Failed to bind RTP server" ); - Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ); + SockAddrInet localAddr; + UdpInetServer rtpDataSocket; + if ( mRtpSource.getLocalHost() != "" ) + localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort(), "udp" ); + else + localAddr.resolve( mRtpSource.getLocalDataPort(), "udp" ); + if ( !rtpDataSocket.bind( localAddr ) ) + Fatal( "Failed to bind RTP server" ); + Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ); - Select select( 3 ); - select.addReader( &rtpDataSocket ); + Select select( 3 ); + select.addReader( &rtpDataSocket ); - unsigned char buffer[ZM_NETWORK_BUFSIZ]; - while ( !mStop && select.wait() >= 0 ) - { - if ( mStop ) - break; - Select::CommsList readable = select.getReadable(); - if ( readable.size() == 0 ) + unsigned char buffer[ZM_NETWORK_BUFSIZ]; + while ( !mStop && select.wait() >= 0 ) + { + if ( mStop ) + break; + Select::CommsList readable = select.getReadable(); + if ( readable.size() == 0 ) + { + Error( "RTP timed out" ); + mStop = true; + break; + } + for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) + { + if ( UdpInetServer *socket = dynamic_cast(*iter) ) + { + int nBytes = socket->recv( buffer, sizeof(buffer) ); + Debug( 4, "Got %d bytes on sd %d", nBytes, socket->getReadDesc() ); + if ( nBytes ) { - Error( "RTP timed out" ); - mStop = true; - break; + recvPacket( buffer, nBytes ); } - for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) + else { - if ( UdpInetServer *socket = dynamic_cast(*iter) ) - { - int nBytes = socket->recv( buffer, sizeof(buffer) ); - Debug( 4, "Got %d bytes on sd %d", nBytes, socket->getReadDesc() ); - if ( nBytes ) - { - recvPacket( buffer, nBytes ); - } - else - { - mStop = true; - break; - } - } - else - { - Panic( "Barfed" ); - } + mStop = true; + break; } - } - rtpDataSocket.close(); - mRtspThread.stop(); - return( 0 ); + } + else + { + Panic( "Barfed" ); + } + } + } + rtpDataSocket.close(); + mRtspThread.stop(); + return( 0 ); } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtp_data.h b/src/zm_rtp_data.h index 6c957a3ad..378c5e2e6 100644 --- a/src/zm_rtp_data.h +++ b/src/zm_rtp_data.h @@ -30,16 +30,16 @@ class RtpSource; struct RtpDataHeader { - uint8_t cc:4; // CSRC count - uint8_t x:1; // header extension flag - uint8_t p:1; // padding flag - uint8_t version:2; // protocol version - uint8_t pt:7; // payload type - uint8_t m:1; // marker bit - uint16_t seqN; // sequence number, network order - uint32_t timestampN; // timestamp, network order - uint32_t ssrcN; // synchronization source, network order - uint32_t csrc[]; // optional CSRC list + uint8_t cc:4; // CSRC count + uint8_t x:1; // header extension flag + uint8_t p:1; // padding flag + uint8_t version:2; // protocol version + uint8_t pt:7; // payload type + uint8_t m:1; // marker bit + uint16_t seqN; // sequence number, network order + uint32_t timestampN; // timestamp, network order + uint32_t ssrcN; // synchronization source, network order + uint32_t csrc[]; // optional CSRC list }; class RtpDataThread : public Thread @@ -47,21 +47,21 @@ class RtpDataThread : public Thread friend class RtspThread; private: - RtspThread &mRtspThread; - RtpSource &mRtpSource; - bool mStop; + RtspThread &mRtspThread; + RtpSource &mRtpSource; + bool mStop; private: - bool recvPacket( const unsigned char *packet, size_t packetLen ); - int run(); + bool recvPacket( const unsigned char *packet, size_t packetLen ); + int run(); public: - RtpDataThread( RtspThread &rtspThread, RtpSource &rtpSource ); + RtpDataThread( RtspThread &rtspThread, RtpSource &rtpSource ); - void stop() - { - mStop = true; - } + void stop() + { + mStop = true; + } }; #endif // ZM_RTP_DATA_H diff --git a/src/zm_rtp_source.cpp b/src/zm_rtp_source.cpp index a61bfffe3..bbdd59a6a 100644 --- a/src/zm_rtp_source.cpp +++ b/src/zm_rtp_source.cpp @@ -27,358 +27,358 @@ #if HAVE_LIBAVCODEC RtpSource::RtpSource( int id, const std::string &localHost, int localPortBase, const std::string &remoteHost, int remotePortBase, uint32_t ssrc, uint16_t seq, uint32_t rtpClock, uint32_t rtpTime, _AVCODECID codecId ) : - mId( id ), - mSsrc( ssrc ), - mLocalHost( localHost ), - mRemoteHost( remoteHost ), - mRtpClock( rtpClock ), - mCodecId( codecId ), - mFrame( 65536 ), - mFrameCount( 0 ), - mFrameGood( true ), - mFrameReady( false ), - mFrameProcessed( false ) + mId( id ), + mSsrc( ssrc ), + mLocalHost( localHost ), + mRemoteHost( remoteHost ), + mRtpClock( rtpClock ), + mCodecId( codecId ), + mFrame( 65536 ), + mFrameCount( 0 ), + mFrameGood( true ), + mFrameReady( false ), + mFrameProcessed( false ) { - char hostname[256] = ""; - gethostname( hostname, sizeof(hostname) ); + char hostname[256] = ""; + gethostname( hostname, sizeof(hostname) ); - mCname = stringtf( "zm-%d@%s", mId, hostname ); - Debug( 3, "RTP CName = %s", mCname.c_str() ); + mCname = stringtf( "zm-%d@%s", mId, hostname ); + Debug( 3, "RTP CName = %s", mCname.c_str() ); - init( seq ); - mMaxSeq = seq - 1; - mProbation = MIN_SEQUENTIAL; + init( seq ); + mMaxSeq = seq - 1; + mProbation = MIN_SEQUENTIAL; - mLocalPortChans[0] = localPortBase; - mLocalPortChans[1] = localPortBase+1; + mLocalPortChans[0] = localPortBase; + mLocalPortChans[1] = localPortBase+1; - mRemotePortChans[0] = remotePortBase; - mRemotePortChans[1] = remotePortBase+1; + mRemotePortChans[0] = remotePortBase; + mRemotePortChans[1] = remotePortBase+1; - mRtpFactor = mRtpClock; + mRtpFactor = mRtpClock; - mBaseTimeReal = tvNow(); - mBaseTimeNtp = tvZero(); - mBaseTimeRtp = rtpTime; + mBaseTimeReal = tvNow(); + mBaseTimeNtp = tvZero(); + mBaseTimeRtp = rtpTime; - mLastSrTimeReal = tvZero(); - mLastSrTimeNtp = tvZero(); - mLastSrTimeRtp = 0; - - if(mCodecId != AV_CODEC_ID_H264 && mCodecId != AV_CODEC_ID_MPEG4) - Warning( "The device is using a codec that may not be supported. Do not be surprised if things don't work." ); + mLastSrTimeReal = tvZero(); + mLastSrTimeNtp = tvZero(); + mLastSrTimeRtp = 0; + + if(mCodecId != AV_CODEC_ID_H264 && mCodecId != AV_CODEC_ID_MPEG4) + Warning( "The device is using a codec that may not be supported. Do not be surprised if things don't work." ); } void RtpSource::init( uint16_t seq ) { - Debug( 3, "Initialising sequence" ); - mBaseSeq = seq; - mMaxSeq = seq; - mBadSeq = RTP_SEQ_MOD + 1; // so seq == mBadSeq is false - mCycles = 0; - mReceivedPackets = 0; - mReceivedPrior = 0; - mExpectedPrior = 0; - // other initialization - mJitter = 0; - mTransit = 0; + Debug( 3, "Initialising sequence" ); + mBaseSeq = seq; + mMaxSeq = seq; + mBadSeq = RTP_SEQ_MOD + 1; // so seq == mBadSeq is false + mCycles = 0; + mReceivedPackets = 0; + mReceivedPrior = 0; + mExpectedPrior = 0; + // other initialization + mJitter = 0; + mTransit = 0; } bool RtpSource::updateSeq( uint16_t seq ) { - uint16_t uDelta = seq - mMaxSeq; + uint16_t uDelta = seq - mMaxSeq; - // Source is not valid until MIN_SEQUENTIAL packets with - // sequential sequence numbers have been received. - Debug( 5, "Seq: %d", seq ); + // Source is not valid until MIN_SEQUENTIAL packets with + // sequential sequence numbers have been received. + Debug( 5, "Seq: %d", seq ); - if ( mProbation) + if ( mProbation) + { + // packet is in sequence + if ( seq == mMaxSeq + 1) { - // packet is in sequence - if ( seq == mMaxSeq + 1) - { - Debug( 3, "Sequence in probation %d, in sequence", mProbation ); - mProbation--; - mMaxSeq = seq; - if ( mProbation == 0 ) - { - init( seq ); - mReceivedPackets++; - return( true ); - } - } - else - { - Warning( "Sequence in probation %d, out of sequence", mProbation ); - mProbation = MIN_SEQUENTIAL - 1; - mMaxSeq = seq; - return( false ); - } + Debug( 3, "Sequence in probation %d, in sequence", mProbation ); + mProbation--; + mMaxSeq = seq; + if ( mProbation == 0 ) + { + init( seq ); + mReceivedPackets++; return( true ); - } - else if ( uDelta < MAX_DROPOUT ) - { - if ( uDelta == 1 ) - { - Debug( 3, "Packet in sequence, gap %d", uDelta ); - } - else - { - Warning( "Packet in sequence, gap %d", uDelta ); - } - - // in order, with permissible gap - if ( seq < mMaxSeq ) - { - // Sequence number wrapped - count another 64K cycle. - mCycles += RTP_SEQ_MOD; - } - mMaxSeq = seq; - } - else if ( uDelta <= RTP_SEQ_MOD - MAX_MISORDER ) - { - Warning( "Packet out of sequence, gap %d", uDelta ); - // the sequence number made a very large jump - if ( seq == mBadSeq ) - { - Debug( 3, "Restarting sequence" ); - // Two sequential packets -- assume that the other side - // restarted without telling us so just re-sync - // (i.e., pretend this was the first packet). - init( seq ); - } - else - { - mBadSeq = (seq + 1) & (RTP_SEQ_MOD-1); - return( false ); - } + } } else { - Warning( "Packet duplicate or reordered, gap %d", uDelta ); - // duplicate or reordered packet - return( false ); + Warning( "Sequence in probation %d, out of sequence", mProbation ); + mProbation = MIN_SEQUENTIAL - 1; + mMaxSeq = seq; + return( false ); } - mReceivedPackets++; - return( uDelta==1?true:false ); + return( true ); + } + else if ( uDelta < MAX_DROPOUT ) + { + if ( uDelta == 1 ) + { + Debug( 3, "Packet in sequence, gap %d", uDelta ); + } + else + { + Warning( "Packet in sequence, gap %d", uDelta ); + } + + // in order, with permissible gap + if ( seq < mMaxSeq ) + { + // Sequence number wrapped - count another 64K cycle. + mCycles += RTP_SEQ_MOD; + } + mMaxSeq = seq; + } + else if ( uDelta <= RTP_SEQ_MOD - MAX_MISORDER ) + { + Warning( "Packet out of sequence, gap %d", uDelta ); + // the sequence number made a very large jump + if ( seq == mBadSeq ) + { + Debug( 3, "Restarting sequence" ); + // Two sequential packets -- assume that the other side + // restarted without telling us so just re-sync + // (i.e., pretend this was the first packet). + init( seq ); + } + else + { + mBadSeq = (seq + 1) & (RTP_SEQ_MOD-1); + return( false ); + } + } + else + { + Warning( "Packet duplicate or reordered, gap %d", uDelta ); + // duplicate or reordered packet + return( false ); + } + mReceivedPackets++; + return( uDelta==1?true:false ); } void RtpSource::updateJitter( const RtpDataHeader *header ) { - if ( mRtpFactor > 0 ) - { - Debug( 5, "Delta rtp = %.6f", tvDiffSec( mBaseTimeReal ) ); - uint32_t localTimeRtp = mBaseTimeRtp + uint32_t( tvDiffSec( mBaseTimeReal ) * mRtpFactor ); - Debug( 5, "Local RTP time = %x", localTimeRtp ); - Debug( 5, "Packet RTP time = %x", ntohl(header->timestampN) ); - uint32_t packetTransit = localTimeRtp - ntohl(header->timestampN); - Debug( 5, "Packet transit RTP time = %x", packetTransit ); + if ( mRtpFactor > 0 ) + { + Debug( 5, "Delta rtp = %.6f", tvDiffSec( mBaseTimeReal ) ); + uint32_t localTimeRtp = mBaseTimeRtp + uint32_t( tvDiffSec( mBaseTimeReal ) * mRtpFactor ); + Debug( 5, "Local RTP time = %x", localTimeRtp ); + Debug( 5, "Packet RTP time = %x", ntohl(header->timestampN) ); + uint32_t packetTransit = localTimeRtp - ntohl(header->timestampN); + Debug( 5, "Packet transit RTP time = %x", packetTransit ); - if ( mTransit > 0 ) - { - // Jitter - int d = packetTransit - mTransit; - Debug( 5, "Jitter D = %d", d ); - if ( d < 0 ) - d = -d; - //mJitter += (1./16.) * ((double)d - mJitter); - mJitter += d - ((mJitter + 8) >> 4); - } - mTransit = packetTransit; - } - else + if ( mTransit > 0 ) { - mJitter = 0; + // Jitter + int d = packetTransit - mTransit; + Debug( 5, "Jitter D = %d", d ); + if ( d < 0 ) + d = -d; + //mJitter += (1./16.) * ((double)d - mJitter); + mJitter += d - ((mJitter + 8) >> 4); } - Debug( 5, "RTP Jitter: %d", mJitter ); + mTransit = packetTransit; + } + else + { + mJitter = 0; + } + Debug( 5, "RTP Jitter: %d", mJitter ); } void RtpSource::updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ) { - struct timeval ntpTime = tvMake( ntpTimeSecs, suseconds_t((USEC_PER_SEC*(ntpTimeFrac>>16))/(1<<16)) ); + struct timeval ntpTime = tvMake( ntpTimeSecs, suseconds_t((USEC_PER_SEC*(ntpTimeFrac>>16))/(1<<16)) ); + Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); + + if ( mBaseTimeNtp.tv_sec == 0 ) + { + mBaseTimeReal = tvNow(); + mBaseTimeNtp = ntpTime; + mBaseTimeRtp = rtpTime; + } + else if ( !mRtpClock ) + { + Debug( 5, "lastSrNtpTime: %ld.%06ld, rtpTime: %x", mLastSrTimeNtp.tv_sec, mLastSrTimeNtp.tv_usec, rtpTime ); Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); - - if ( mBaseTimeNtp.tv_sec == 0 ) - { - mBaseTimeReal = tvNow(); - mBaseTimeNtp = ntpTime; - mBaseTimeRtp = rtpTime; - } - else if ( !mRtpClock ) - { - Debug( 5, "lastSrNtpTime: %ld.%06ld, rtpTime: %x", mLastSrTimeNtp.tv_sec, mLastSrTimeNtp.tv_usec, rtpTime ); - Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); - double diffNtpTime = tvDiffSec( mBaseTimeNtp, ntpTime ); - uint32_t diffRtpTime = rtpTime - mBaseTimeRtp; + double diffNtpTime = tvDiffSec( mBaseTimeNtp, ntpTime ); + uint32_t diffRtpTime = rtpTime - mBaseTimeRtp; - //Debug( 5, "Real-diff: %.6f", diffRealTime ); - Debug( 5, "NTP-diff: %.6f", diffNtpTime ); - Debug( 5, "RTP-diff: %d", diffRtpTime ); + //Debug( 5, "Real-diff: %.6f", diffRealTime ); + Debug( 5, "NTP-diff: %.6f", diffNtpTime ); + Debug( 5, "RTP-diff: %d", diffRtpTime ); - mRtpFactor = (uint32_t)(diffRtpTime / diffNtpTime); + mRtpFactor = (uint32_t)(diffRtpTime / diffNtpTime); - Debug( 5, "RTPfactor: %d", mRtpFactor ); - } - mLastSrTimeNtpSecs = ntpTimeSecs; - mLastSrTimeNtpFrac = ntpTimeFrac; - mLastSrTimeNtp = ntpTime; - mLastSrTimeRtp = rtpTime; + Debug( 5, "RTPfactor: %d", mRtpFactor ); + } + mLastSrTimeNtpSecs = ntpTimeSecs; + mLastSrTimeNtpFrac = ntpTimeFrac; + mLastSrTimeNtp = ntpTime; + mLastSrTimeRtp = rtpTime; } void RtpSource::updateRtcpStats() { - uint32_t extendedMax = mCycles + mMaxSeq; - mExpectedPackets = extendedMax - mBaseSeq + 1; + uint32_t extendedMax = mCycles + mMaxSeq; + mExpectedPackets = extendedMax - mBaseSeq + 1; - Debug( 5, "Expected packets = %d", mExpectedPackets ); + Debug( 5, "Expected packets = %d", mExpectedPackets ); - // The number of packets lost is defined to be the number of packets - // expected less the number of packets actually received: - mLostPackets = mExpectedPackets - mReceivedPackets; - Debug( 5, "Lost packets = %d", mLostPackets ); + // The number of packets lost is defined to be the number of packets + // expected less the number of packets actually received: + mLostPackets = mExpectedPackets - mReceivedPackets; + Debug( 5, "Lost packets = %d", mLostPackets ); - uint32_t expectedInterval = mExpectedPackets - mExpectedPrior; - Debug( 5, "Expected interval = %d", expectedInterval ); - mExpectedPrior = mExpectedPackets; - uint32_t receivedInterval = mReceivedPackets - mReceivedPrior; - Debug( 5, "Received interval = %d", receivedInterval ); - mReceivedPrior = mReceivedPackets; - uint32_t lostInterval = expectedInterval - receivedInterval; - Debug( 5, "Lost interval = %d", lostInterval ); + uint32_t expectedInterval = mExpectedPackets - mExpectedPrior; + Debug( 5, "Expected interval = %d", expectedInterval ); + mExpectedPrior = mExpectedPackets; + uint32_t receivedInterval = mReceivedPackets - mReceivedPrior; + Debug( 5, "Received interval = %d", receivedInterval ); + mReceivedPrior = mReceivedPackets; + uint32_t lostInterval = expectedInterval - receivedInterval; + Debug( 5, "Lost interval = %d", lostInterval ); - if ( expectedInterval == 0 || lostInterval <= 0 ) - mLostFraction = 0; - else - mLostFraction = (lostInterval << 8) / expectedInterval; - Debug( 5, "Lost fraction = %d", mLostFraction ); + if ( expectedInterval == 0 || lostInterval <= 0 ) + mLostFraction = 0; + else + mLostFraction = (lostInterval << 8) / expectedInterval; + Debug( 5, "Lost fraction = %d", mLostFraction ); } bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) { - const RtpDataHeader *rtpHeader; - rtpHeader = (RtpDataHeader *)packet; - int rtpHeaderSize = 12 + rtpHeader->cc * 4; - // No need to check for nal type as non fragmented packets already have 001 start sequence appended - bool h264FragmentEnd = (mCodecId == AV_CODEC_ID_H264) && (packet[rtpHeaderSize+1] & 0x40); - bool thisM = rtpHeader->m || h264FragmentEnd; + const RtpDataHeader *rtpHeader; + rtpHeader = (RtpDataHeader *)packet; + int rtpHeaderSize = 12 + rtpHeader->cc * 4; + // No need to check for nal type as non fragmented packets already have 001 start sequence appended + bool h264FragmentEnd = (mCodecId == AV_CODEC_ID_H264) && (packet[rtpHeaderSize+1] & 0x40); + bool thisM = rtpHeader->m || h264FragmentEnd; - if ( updateSeq( ntohs(rtpHeader->seqN) ) ) + if ( updateSeq( ntohs(rtpHeader->seqN) ) ) + { + Hexdump( 4, packet+rtpHeaderSize, 16 ); + + if ( mFrameGood ) { - Hexdump( 4, packet+rtpHeaderSize, 16 ); - - if ( mFrameGood ) + int extraHeader = 0; + + if( mCodecId == AV_CODEC_ID_H264 ) + { + int nalType = (packet[rtpHeaderSize] & 0x1f); + + switch (nalType) { - int extraHeader = 0; - - if( mCodecId == AV_CODEC_ID_H264 ) + case 24: + { + extraHeader = 2; + break; + } + case 25: case 26: case 27: + { + extraHeader = 3; + break; + } + // FU-A and FU-B + case 28: case 29: + { + // Is this NAL the first NAL in fragmentation sequence + if ( packet[rtpHeaderSize+1] & 0x80 ) { - int nalType = (packet[rtpHeaderSize] & 0x1f); - - switch (nalType) - { - case 24: - { - extraHeader = 2; - break; - } - case 25: case 26: case 27: - { - extraHeader = 3; - break; - } - // FU-A and FU-B - case 28: case 29: - { - // Is this NAL the first NAL in fragmentation sequence - if ( packet[rtpHeaderSize+1] & 0x80 ) - { - // Now we will form new header of frame - mFrame.append( "\x0\x0\x1\x0", 4 ); - // Reconstruct NAL header from FU headers - *(mFrame+3) = (packet[rtpHeaderSize+1] & 0x1f) | - (packet[rtpHeaderSize] & 0xe0); - } - - extraHeader = 2; - break; - } - } - - // Append NAL frame start code - if ( !mFrame.size() ) - mFrame.append( "\x0\x0\x1", 3 ); + // Now we will form new header of frame + mFrame.append( "\x0\x0\x1\x0", 4 ); + // Reconstruct NAL header from FU headers + *(mFrame+3) = (packet[rtpHeaderSize+1] & 0x1f) | + (packet[rtpHeaderSize] & 0xe0); } - mFrame.append( packet+rtpHeaderSize+extraHeader, packetLen-rtpHeaderSize-extraHeader ); - } - - Hexdump( 4, mFrame.head(), 16 ); - - if ( thisM ) - { - if ( mFrameGood ) - { - Debug( 2, "Got new frame %d, %d bytes", mFrameCount, mFrame.size() ); - - mFrameProcessed.setValueImmediate( false ); - mFrameReady.updateValueSignal( true ); - if ( !mFrameProcessed.getValueImmediate() ) - { - for ( int count = 0; !mFrameProcessed.getUpdatedValue( 1 ); count++ ) - if( count > 1 ) - return( false ); - } - mFrameCount++; - } - else - { - Warning( "Discarding incomplete frame %d, %d bytes", mFrameCount, mFrame.size() ); - } - mFrame.clear(); + + extraHeader = 2; + break; + } } + + // Append NAL frame start code + if ( !mFrame.size() ) + mFrame.append( "\x0\x0\x1", 3 ); + } + mFrame.append( packet+rtpHeaderSize+extraHeader, packetLen-rtpHeaderSize-extraHeader ); } - else - { - if ( mFrame.size() ) - { - Warning( "Discarding partial frame %d, %d bytes", mFrameCount, mFrame.size() ); - } - else - { - Warning( "Discarding frame %d", mFrameCount ); - } - mFrameGood = false; - mFrame.clear(); - } + + Hexdump( 4, mFrame.head(), 16 ); + if ( thisM ) { - mFrameGood = true; - prevM = true; + if ( mFrameGood ) + { + Debug( 2, "Got new frame %d, %d bytes", mFrameCount, mFrame.size() ); + + mFrameProcessed.setValueImmediate( false ); + mFrameReady.updateValueSignal( true ); + if ( !mFrameProcessed.getValueImmediate() ) + { + for ( int count = 0; !mFrameProcessed.getUpdatedValue( 1 ); count++ ) + if( count > 1 ) + return( false ); + } + mFrameCount++; + } + else + { + Warning( "Discarding incomplete frame %d, %d bytes", mFrameCount, mFrame.size() ); + } + mFrame.clear(); + } + } + else + { + if ( mFrame.size() ) + { + Warning( "Discarding partial frame %d, %d bytes", mFrameCount, mFrame.size() ); } else - prevM = false; + { + Warning( "Discarding frame %d", mFrameCount ); + } + mFrameGood = false; + mFrame.clear(); + } + if ( thisM ) + { + mFrameGood = true; + prevM = true; + } + else + prevM = false; - updateJitter( rtpHeader ); + updateJitter( rtpHeader ); - return( true ); + return( true ); } bool RtpSource::getFrame( Buffer &buffer ) { - Debug( 3, "Getting frame" ); - if ( !mFrameReady.getValueImmediate() ) - { - // Allow for a couple of spurious returns - for ( int count = 0; !mFrameReady.getUpdatedValue( 1 ); count++ ) - if ( count > 1 ) - return( false ); - } - buffer = mFrame; - mFrameReady.setValueImmediate( false ); - mFrameProcessed.updateValueSignal( true ); - Debug( 3, "Copied %d bytes", buffer.size() ); - return( true ); + Debug( 3, "Getting frame" ); + if ( !mFrameReady.getValueImmediate() ) + { + // Allow for a couple of spurious returns + for ( int count = 0; !mFrameReady.getUpdatedValue( 1 ); count++ ) + if ( count > 1 ) + return( false ); + } + buffer = mFrame; + mFrameReady.setValueImmediate( false ); + mFrameProcessed.updateValueSignal( true ); + Debug( 3, "Copied %d bytes", buffer.size() ); + return( true ); } #endif // HAVE_LIBAVCODEC diff --git a/src/zm_rtp_source.h b/src/zm_rtp_source.h index cd41424ac..b86577e01 100644 --- a/src/zm_rtp_source.h +++ b/src/zm_rtp_source.h @@ -35,152 +35,152 @@ struct RtpDataHeader; class RtpSource { public: - typedef enum { EMPTY, FILLING, READY } FrameState; + typedef enum { EMPTY, FILLING, READY } FrameState; private: - static const int RTP_SEQ_MOD = 1<<16; - static const int MAX_DROPOUT = 3000; - static const int MAX_MISORDER = 100; - static const int MIN_SEQUENTIAL = 2; + static const int RTP_SEQ_MOD = 1<<16; + static const int MAX_DROPOUT = 3000; + static const int MAX_MISORDER = 100; + static const int MIN_SEQUENTIAL = 2; private: - // Identity - int mId; // General id (usually monitor id) - std::string mCname; // Canonical name, for SDES + // Identity + int mId; // General id (usually monitor id) + std::string mCname; // Canonical name, for SDES - // RTP/RTCP fields - uint32_t mSsrc; - uint16_t mMaxSeq; // highest seq. number seen - uint32_t mCycles; // shifted count of seq. number cycles - uint32_t mBaseSeq; // base seq number - uint32_t mBadSeq; // last 'bad' seq number + 1 - uint32_t mProbation; // sequ. packets till source is valid - uint32_t mReceivedPackets; // packets received - uint32_t mExpectedPrior; // packet expected at last interval - uint32_t mReceivedPrior; // packet received at last interval - uint32_t mTransit; // relative trans time for prev pkt - uint32_t mJitter; // estimated jitter - - // Ports/Channels - std::string mLocalHost; - int mLocalPortChans[2]; - std::string mRemoteHost; - int mRemotePortChans[2]; + // RTP/RTCP fields + uint32_t mSsrc; + uint16_t mMaxSeq; // highest seq. number seen + uint32_t mCycles; // shifted count of seq. number cycles + uint32_t mBaseSeq; // base seq number + uint32_t mBadSeq; // last 'bad' seq number + 1 + uint32_t mProbation; // sequ. packets till source is valid + uint32_t mReceivedPackets; // packets received + uint32_t mExpectedPrior; // packet expected at last interval + uint32_t mReceivedPrior; // packet received at last interval + uint32_t mTransit; // relative trans time for prev pkt + uint32_t mJitter; // estimated jitter + + // Ports/Channels + std::string mLocalHost; + int mLocalPortChans[2]; + std::string mRemoteHost; + int mRemotePortChans[2]; - // Time keys - uint32_t mRtpClock; - uint32_t mRtpFactor; - struct timeval mBaseTimeReal; - struct timeval mBaseTimeNtp; - uint32_t mBaseTimeRtp; + // Time keys + uint32_t mRtpClock; + uint32_t mRtpFactor; + struct timeval mBaseTimeReal; + struct timeval mBaseTimeNtp; + uint32_t mBaseTimeRtp; - struct timeval mLastSrTimeReal; - uint32_t mLastSrTimeNtpSecs; - uint32_t mLastSrTimeNtpFrac; - struct timeval mLastSrTimeNtp; - uint32_t mLastSrTimeRtp; + struct timeval mLastSrTimeReal; + uint32_t mLastSrTimeNtpSecs; + uint32_t mLastSrTimeNtpFrac; + struct timeval mLastSrTimeNtp; + uint32_t mLastSrTimeRtp; - // Stats, intermittently updated - uint32_t mExpectedPackets; - uint32_t mLostPackets; - uint8_t mLostFraction; + // Stats, intermittently updated + uint32_t mExpectedPackets; + uint32_t mLostPackets; + uint8_t mLostFraction; - _AVCODECID mCodecId; + _AVCODECID mCodecId; - Buffer mFrame; - int mFrameCount; - bool mFrameGood; - bool prevM; - ThreadData mFrameReady; - ThreadData mFrameProcessed; + Buffer mFrame; + int mFrameCount; + bool mFrameGood; + bool prevM; + ThreadData mFrameReady; + ThreadData mFrameProcessed; private: - void init( uint16_t seq ); + void init( uint16_t seq ); public: - RtpSource( int id, const std::string &localHost, int localPortBase, const std::string &remoteHost, int remotePortBase, uint32_t ssrc, uint16_t seq, uint32_t rtpClock, uint32_t rtpTime, _AVCODECID codecId ); - - bool updateSeq( uint16_t seq ); - void updateJitter( const RtpDataHeader *header ); - void updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ); - void updateRtcpStats(); + RtpSource( int id, const std::string &localHost, int localPortBase, const std::string &remoteHost, int remotePortBase, uint32_t ssrc, uint16_t seq, uint32_t rtpClock, uint32_t rtpTime, _AVCODECID codecId ); + + bool updateSeq( uint16_t seq ); + void updateJitter( const RtpDataHeader *header ); + void updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ); + void updateRtcpStats(); - bool handlePacket( const unsigned char *packet, size_t packetLen ); + bool handlePacket( const unsigned char *packet, size_t packetLen ); - uint32_t getSsrc() const - { - return( mSsrc ); - } - void setSsrc( uint32_t ssrc ) - { - mSsrc = ssrc; - } + uint32_t getSsrc() const + { + return( mSsrc ); + } + void setSsrc( uint32_t ssrc ) + { + mSsrc = ssrc; + } - bool getFrame( Buffer &buffer ); + bool getFrame( Buffer &buffer ); - const std::string &getCname() const - { - return( mCname ); - } + const std::string &getCname() const + { + return( mCname ); + } - const std::string &getLocalHost() const - { - return( mLocalHost ); - } + const std::string &getLocalHost() const + { + return( mLocalHost ); + } - int getLocalDataPort() const - { - return( mLocalPortChans[0] ); - } + int getLocalDataPort() const + { + return( mLocalPortChans[0] ); + } - int getLocalCtrlPort() const - { - return( mLocalPortChans[1] ); - } + int getLocalCtrlPort() const + { + return( mLocalPortChans[1] ); + } - const std::string &getRemoteHost() const - { - return( mRemoteHost ); - } + const std::string &getRemoteHost() const + { + return( mRemoteHost ); + } - int getRemoteDataPort() const - { - return( mRemotePortChans[0] ); - } + int getRemoteDataPort() const + { + return( mRemotePortChans[0] ); + } - int getRemoteCtrlPort() const - { - return( mRemotePortChans[1] ); - } + int getRemoteCtrlPort() const + { + return( mRemotePortChans[1] ); + } - uint32_t getMaxSeq() const - { - return( mCycles + mMaxSeq ); - } + uint32_t getMaxSeq() const + { + return( mCycles + mMaxSeq ); + } - uint32_t getExpectedPackets() const - { - return( mExpectedPackets ); - } - - uint32_t getLostPackets() const - { - return( mLostPackets ); - } + uint32_t getExpectedPackets() const + { + return( mExpectedPackets ); + } + + uint32_t getLostPackets() const + { + return( mLostPackets ); + } - uint8_t getLostFraction() const - { - return( mLostFraction ); - } + uint8_t getLostFraction() const + { + return( mLostFraction ); + } - uint32_t getJitter() const - { - return( mJitter >> 4 ); - } + uint32_t getJitter() const + { + return( mJitter >> 4 ); + } - uint32_t getLastSrTimestamp() const - { - return( ((mLastSrTimeNtpSecs&0xffff)<<16)|(mLastSrTimeNtpFrac>>16) ); - } + uint32_t getLastSrTimestamp() const + { + return( ((mLastSrTimeNtpSecs&0xffff)<<16)|(mLastSrTimeNtpFrac>>16) ); + } }; #endif // HAVE_LIBAVCODEC diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp index 7ac80e9b6..b248d1f05 100644 --- a/src/zm_rtsp.cpp +++ b/src/zm_rtsp.cpp @@ -38,860 +38,860 @@ RtspThread::PortSet RtspThread::smAssignedPorts; bool RtspThread::sendCommand( std::string message ) { - if ( mNeedAuth ) { - StringVector parts = split( message, " " ); - if (parts.size() > 1) - message += mAuthenticator->getAuthHeader(parts[0], parts[1]); - } - message += stringtf( "User-Agent: ZoneMinder/%s\r\n", ZM_VERSION ); - message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq ); - Debug( 2, "Sending RTSP message: %s", message.c_str() ); - if ( mMethod == RTP_RTSP_HTTP ) + if ( mNeedAuth ) { + StringVector parts = split( message, " " ); + if (parts.size() > 1) + message += mAuthenticator->getAuthHeader(parts[0], parts[1]); + } + message += stringtf( "User-Agent: ZoneMinder/%s\r\n", ZM_VERSION ); + message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq ); + Debug( 2, "Sending RTSP message: %s", message.c_str() ); + if ( mMethod == RTP_RTSP_HTTP ) + { + message = base64Encode( message ); + Debug( 2, "Sending encoded RTSP message: %s", message.c_str() ); + if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) { - message = base64Encode( message ); - Debug( 2, "Sending encoded RTSP message: %s", message.c_str() ); - if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) - { - Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); - return( false ); - } + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( false ); } - else + } + else + { + if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) { - if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) - { - Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); - return( false ); - } + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( false ); } - return( true ); + } + return( true ); } bool RtspThread::recvResponse( std::string &response ) { - if ( mRtspSocket.recv( response ) < 0 ) - Error( "Recv failed; %s", strerror(errno) ); - Debug( 2, "Received RTSP response: %s (%zd bytes)", response.c_str(), response.size() ); - float respVer = 0; - respCode = -1; - char respText[ZM_NETWORK_BUFSIZ]; - if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) + if ( mRtspSocket.recv( response ) < 0 ) + Error( "Recv failed; %s", strerror(errno) ); + Debug( 2, "Received RTSP response: %s (%zd bytes)", response.c_str(), response.size() ); + float respVer = 0; + respCode = -1; + char respText[ZM_NETWORK_BUFSIZ]; + if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) + { + if ( isalnum(response[0]) ) { - if ( isalnum(response[0]) ) - { - Error( "Response parse failure in '%s'", response.c_str() ); - } - else - { - Error( "Response parse failure, %zd bytes follow", response.size() ); - if ( response.size() ) - Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); - } - return( false ); + Error( "Response parse failure in '%s'", response.c_str() ); } - if ( respCode == 401) + else { - Debug( 2, "Got 401 access denied response code, check WWW-Authenticate header and retry"); - mAuthenticator->checkAuthResponse(response); - mNeedAuth = true; - return( false ); - } - else if ( respCode != 200 ) - { - Error( "Unexpected response code %d, text is '%s'", respCode, respText ); - return( false ); + Error( "Response parse failure, %zd bytes follow", response.size() ); + if ( response.size() ) + Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); } - return( true ); + return( false ); + } + if ( respCode == 401) + { + Debug( 2, "Got 401 access denied response code, check WWW-Authenticate header and retry"); + mAuthenticator->checkAuthResponse(response); + mNeedAuth = true; + return( false ); + } + else if ( respCode != 200 ) + { + Error( "Unexpected response code %d, text is '%s'", respCode, respText ); + return( false ); + } + return( true ); } int RtspThread::requestPorts() { - if ( !smMinDataPort ) + if ( !smMinDataPort ) + { + char sql[ZM_SQL_SML_BUFSIZ]; + strncpy( sql, "select Id from Monitors where Function != 'None' and Type = 'Remote' and Protocol = 'rtsp' and Method = 'rtpUni' order by Id asc", sizeof(sql) ); + if ( mysql_query( &dbconn, sql ) ) { - char sql[ZM_SQL_SML_BUFSIZ]; - strncpy( sql, "select Id from Monitors where Function != 'None' and Type = 'Remote' and Protocol = 'rtsp' and Method = 'rtpUni' order by Id asc", sizeof(sql) ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int nMonitors = mysql_num_rows( result ); - int position = 0; - if ( nMonitors ) - { - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int id = atoi(dbrow[0]); - if ( mId == id ) - { - position = i; - break; - } - } - } - else - { - // Minor hack for testing when not strictly enabled - nMonitors = 1; - position = 0; - } - mysql_free_result(result); - int portRange = int(((config.max_rtp_port-config.min_rtp_port)+1)/nMonitors); - smMinDataPort = config.min_rtp_port + (position * portRange); - smMaxDataPort = smMinDataPort + portRange - 1; - Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort ); - } - for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) { - PortSet::const_iterator iter = smAssignedPorts.find( i ); - if ( iter == smAssignedPorts.end() ) - { - smAssignedPorts.insert( i ); - return( i ); - } + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); } - Panic( "Can assign RTP port, no ports left in pool" ); - return( -1 ); + int nMonitors = mysql_num_rows( result ); + int position = 0; + if ( nMonitors ) + { + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int id = atoi(dbrow[0]); + if ( mId == id ) + { + position = i; + break; + } + } + } + else + { + // Minor hack for testing when not strictly enabled + nMonitors = 1; + position = 0; + } + mysql_free_result(result); + int portRange = int(((config.max_rtp_port-config.min_rtp_port)+1)/nMonitors); + smMinDataPort = config.min_rtp_port + (position * portRange); + smMaxDataPort = smMinDataPort + portRange - 1; + Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort ); + } + for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) + { + PortSet::const_iterator iter = smAssignedPorts.find( i ); + if ( iter == smAssignedPorts.end() ) + { + smAssignedPorts.insert( i ); + return( i ); + } + } + Panic( "Can assign RTP port, no ports left in pool" ); + return( -1 ); } void RtspThread::releasePorts( int port ) { - if ( port > 0 ) - smAssignedPorts.erase( port ); + if ( port > 0 ) + smAssignedPorts.erase( port ); } RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth, bool rtsp_describe) : - mId( id ), - mMethod( method ), - mProtocol( protocol ), - mHost( host ), - mPort( port ), - mPath( path ), - mRtspDescribe( rtsp_describe ), - mSessDesc( 0 ), - mFormatContext( 0 ), - mSeq( 0 ), - mSession( 0 ), - mSsrc( 0 ), - mDist( UNDEFINED ), - mRtpTime( 0 ), - mStop( false ) + mId( id ), + mMethod( method ), + mProtocol( protocol ), + mHost( host ), + mPort( port ), + mPath( path ), + mRtspDescribe( rtsp_describe ), + mSessDesc( 0 ), + mFormatContext( 0 ), + mSeq( 0 ), + mSession( 0 ), + mSsrc( 0 ), + mDist( UNDEFINED ), + mRtpTime( 0 ), + mStop( false ) { - mUrl = mProtocol+"://"+mHost+":"+mPort; - if ( !mPath.empty() ) - { - if ( mPath[0] == '/' ) - mUrl += mPath; - else - mUrl += '/'+mPath; - } - - mSsrc = rand(); - - Debug( 2, "RTSP Local SSRC is %x", mSsrc ); - - if ( mMethod == RTP_RTSP_HTTP ) - mHttpSession = stringtf( "%d", rand() ); - - mNeedAuth = false; - StringVector parts = split(auth,":"); - if (parts.size() > 1) - mAuthenticator = new zm::Authenticator(parts[0], parts[1]); + mUrl = mProtocol+"://"+mHost+":"+mPort; + if ( !mPath.empty() ) + { + if ( mPath[0] == '/' ) + mUrl += mPath; else - mAuthenticator = new zm::Authenticator(parts[0], ""); + mUrl += '/'+mPath; + } + + mSsrc = rand(); + + Debug( 2, "RTSP Local SSRC is %x", mSsrc ); + + if ( mMethod == RTP_RTSP_HTTP ) + mHttpSession = stringtf( "%d", rand() ); + + mNeedAuth = false; + StringVector parts = split(auth,":"); + if (parts.size() > 1) + mAuthenticator = new zm::Authenticator(parts[0], parts[1]); + else + mAuthenticator = new zm::Authenticator(parts[0], ""); } RtspThread::~RtspThread() { - if ( mFormatContext ) - { + if ( mFormatContext ) + { #if LIBAVFORMAT_VERSION_CHECK(52, 96, 0, 96, 0) - avformat_free_context( mFormatContext ); + avformat_free_context( mFormatContext ); #else - av_free_format_context( mFormatContext ); + av_free_format_context( mFormatContext ); #endif - mFormatContext = NULL; - } - if ( mSessDesc ) - { - delete mSessDesc; - mSessDesc = NULL; - } - delete mAuthenticator; + mFormatContext = NULL; + } + if ( mSessDesc ) + { + delete mSessDesc; + mSessDesc = NULL; + } + delete mAuthenticator; } int RtspThread::run() { - std::string message; - std::string response; + std::string message; + std::string response; - response.reserve( ZM_NETWORK_BUFSIZ ); + response.reserve( ZM_NETWORK_BUFSIZ ); - if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) - Fatal( "Unable to connect RTSP socket" ); + if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) + Fatal( "Unable to connect RTSP socket" ); + //Select select( 0.25 ); + //select.addReader( &mRtspSocket ); + //while ( select.wait() ) + //{ + //mRtspSocket.recv( response ); + //Debug( 4, "Drained %d bytes from RTSP socket", response.size() ); + //} + + + bool authTried = false; + if ( mMethod == RTP_RTSP_HTTP ) + { + if ( !mRtspSocket2.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) + Fatal( "Unable to connect auxiliary RTSP/HTTP socket" ); //Select select( 0.25 ); - //select.addReader( &mRtspSocket ); + //select.addReader( &mRtspSocket2 ); //while ( select.wait() ) //{ - //mRtspSocket.recv( response ); - //Debug( 4, "Drained %d bytes from RTSP socket", response.size() ); + //mRtspSocket2.recv( response ); + //Debug( 4, "Drained %d bytes from HTTP socket", response.size() ); //} - - bool authTried = false; - if ( mMethod == RTP_RTSP_HTTP ) + //possibly retry sending the message for authentication + int respCode = -1; + char respText[256]; + do { + message = "GET "+mPath+" HTTP/1.0\r\n"; + message += "X-SessionCookie: "+mHttpSession+"\r\n"; + if ( mNeedAuth ) { + message += mAuthenticator->getAuthHeader("GET", mPath); + authTried = true; + } + message += "Accept: application/x-rtsp-tunnelled\r\n"; + message += "\r\n"; + Debug( 2, "Sending HTTP message: %s", message.c_str() ); + if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) + { + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( -1 ); + } + if ( mRtspSocket.recv( response ) < 0 ) + { + Error( "Recv failed; %s", strerror(errno) ); + return( -1 ); + } + + Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() ); + float respVer = 0; + respCode = -1; + if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) + { + if ( isalnum(response[0]) ) + { + Error( "Response parse failure in '%s'", response.c_str() ); + } + else + { + Error( "Response parse failure, %zd bytes follow", response.size() ); + if ( response.size() ) + Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); + } + return( -1 ); + } + // If Server requests authentication, check WWW-Authenticate header and fill required fields + // for requested authentication method + if (respCode == 401 && !authTried) { + mNeedAuth = true; + mAuthenticator->checkAuthResponse(response); + Debug(2, "Processed 401 response"); + mRtspSocket.close(); + if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) + Fatal( "Unable to reconnect RTSP socket" ); + Debug(2, "connection should be reopened now"); + } + + } while (respCode == 401 && !authTried); + + if ( respCode != 200 ) { - if ( !mRtspSocket2.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) - Fatal( "Unable to connect auxiliary RTSP/HTTP socket" ); - //Select select( 0.25 ); - //select.addReader( &mRtspSocket2 ); - //while ( select.wait() ) - //{ - //mRtspSocket2.recv( response ); - //Debug( 4, "Drained %d bytes from HTTP socket", response.size() ); - //} - - //possibly retry sending the message for authentication - int respCode = -1; - char respText[256]; - do { - message = "GET "+mPath+" HTTP/1.0\r\n"; - message += "X-SessionCookie: "+mHttpSession+"\r\n"; - if ( mNeedAuth ) { - message += mAuthenticator->getAuthHeader("GET", mPath); - authTried = true; - } - message += "Accept: application/x-rtsp-tunnelled\r\n"; - message += "\r\n"; - Debug( 2, "Sending HTTP message: %s", message.c_str() ); - if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) - { - Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); - return( -1 ); - } - if ( mRtspSocket.recv( response ) < 0 ) - { - Error( "Recv failed; %s", strerror(errno) ); - return( -1 ); - } - - Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() ); - float respVer = 0; - respCode = -1; - if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) - { - if ( isalnum(response[0]) ) - { - Error( "Response parse failure in '%s'", response.c_str() ); - } - else - { - Error( "Response parse failure, %zd bytes follow", response.size() ); - if ( response.size() ) - Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); - } - return( -1 ); - } - // If Server requests authentication, check WWW-Authenticate header and fill required fields - // for requested authentication method - if (respCode == 401 && !authTried) { - mNeedAuth = true; - mAuthenticator->checkAuthResponse(response); - Debug(2, "Processed 401 response"); - mRtspSocket.close(); - if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) - Fatal( "Unable to reconnect RTSP socket" ); - Debug(2, "connection should be reopened now"); - } - - } while (respCode == 401 && !authTried); - - if ( respCode != 200 ) - { - Error( "Unexpected response code %d, text is '%s'", respCode, respText ); - return( -1 ); - } - - message = "POST "+mPath+" HTTP/1.0\r\n"; - message += "X-SessionCookie: "+mHttpSession+"\r\n"; - if ( mNeedAuth ) - message += mAuthenticator->getAuthHeader("POST", mPath); - message += "Content-Length: 32767\r\n"; - message += "Content-Type: application/x-rtsp-tunnelled\r\n"; - message += "\r\n"; - Debug( 2, "Sending HTTP message: %s", message.c_str() ); - if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) - { - Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); - return( -1 ); - } + Error( "Unexpected response code %d, text is '%s'", respCode, respText ); + return( -1 ); } - std::string localHost = ""; - int localPorts[2] = { 0, 0 }; + message = "POST "+mPath+" HTTP/1.0\r\n"; + message += "X-SessionCookie: "+mHttpSession+"\r\n"; + if ( mNeedAuth ) + message += mAuthenticator->getAuthHeader("POST", mPath); + message += "Content-Length: 32767\r\n"; + message += "Content-Type: application/x-rtsp-tunnelled\r\n"; + message += "\r\n"; + Debug( 2, "Sending HTTP message: %s", message.c_str() ); + if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) + { + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( -1 ); + } + } - // Request supported RTSP commands by the server - message = "OPTIONS "+mUrl+" RTSP/1.0\r\n"; - if ( !sendCommand( message ) ) + std::string localHost = ""; + int localPorts[2] = { 0, 0 }; + + // Request supported RTSP commands by the server + message = "OPTIONS "+mUrl+" RTSP/1.0\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + + // A negative return here may indicate auth failure, but we will have setup the auth mechanisms so we need to retry. + if ( !recvResponse( response ) ) { + if ( mNeedAuth ) { + Debug( 2, "Resending OPTIONS due to possible auth requirement" ); + if ( !sendCommand( message ) ) return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + } else { + return( -1 ); + } + } // end if failed response maybe due to auth - // A negative return here may indicate auth failure, but we will have setup the auth mechanisms so we need to retry. - if ( !recvResponse( response ) ) { - if ( mNeedAuth ) { - Debug( 2, "Resending OPTIONS due to possible auth requirement" ); - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); - } else { - return( -1 ); - } - } // end if failed response maybe due to auth + char publicLine[256] = ""; + StringVector lines = split( response, "\r\n" ); + for ( size_t i = 0; i < lines.size(); i++ ) + sscanf( lines[i].c_str(), "Public: %[^\r\n]\r\n", publicLine ); - char publicLine[256] = ""; - StringVector lines = split( response, "\r\n" ); + // Check if the server supports the GET_PARAMETER command + // If yes, it is likely that the server will request this command as a keepalive message + bool sendKeepalive = false; + if ( publicLine[0] && strstr(publicLine, "GET_PARAMETER") ) + sendKeepalive = true; + + message = "DESCRIBE "+mUrl+" RTSP/1.0\r\n"; + bool res; + do { + if (mNeedAuth) + authTried = true; + sendCommand( message ); + sleep( 1 ); + res = recvResponse( response ); + if (!res && respCode==401) + mNeedAuth = true; + } while (!res && respCode==401 && !authTried); + + const std::string endOfHeaders = "\r\n\r\n"; + size_t sdpStart = response.find( endOfHeaders ); + if( sdpStart == std::string::npos ) + return( -1 ); + + if ( mRtspDescribe ) + { + std::string DescHeader = response.substr( 0,sdpStart ); + Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() ); + + lines = split( DescHeader, "\r\n" ); for ( size_t i = 0; i < lines.size(); i++ ) - sscanf( lines[i].c_str(), "Public: %[^\r\n]\r\n", publicLine ); + { + // If the device sends us a url value for Content-Base in the response header, we should use that instead + if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) + { + mUrl = trimSpaces( lines[i].substr( 13 ) ); + Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() ); + break; + } + } + } - // Check if the server supports the GET_PARAMETER command - // If yes, it is likely that the server will request this command as a keepalive message - bool sendKeepalive = false; - if ( publicLine[0] && strstr(publicLine, "GET_PARAMETER") ) - sendKeepalive = true; + sdpStart += endOfHeaders.length(); - message = "DESCRIBE "+mUrl+" RTSP/1.0\r\n"; - bool res; - do { - if (mNeedAuth) - authTried = true; - sendCommand( message ); - sleep( 1 ); - res = recvResponse( response ); - if (!res && respCode==401) - mNeedAuth = true; - } while (!res && respCode==401 && !authTried); + std::string sdp = response.substr( sdpStart ); + Debug( 1, "Processing SDP '%s'", sdp.c_str() ); - const std::string endOfHeaders = "\r\n\r\n"; - size_t sdpStart = response.find( endOfHeaders ); - if( sdpStart == std::string::npos ) - return( -1 ); - - if ( mRtspDescribe ) - { - std::string DescHeader = response.substr( 0,sdpStart ); - Debug( 1, "Processing DESCRIBE response header '%s'", DescHeader.c_str() ); - - lines = split( DescHeader, "\r\n" ); - for ( size_t i = 0; i < lines.size(); i++ ) - { - // If the device sends us a url value for Content-Base in the response header, we should use that instead - if ( ( lines[i].size() > 13 ) && ( lines[i].substr( 0, 13 ) == "Content-Base:" ) ) - { - mUrl = trimSpaces( lines[i].substr( 13 ) ); - Info("Received new Content-Base in DESCRIBE response header. Updated device Url to: '%s'", mUrl.c_str() ); - break; - } - } - } - - sdpStart += endOfHeaders.length(); - - std::string sdp = response.substr( sdpStart ); - Debug( 1, "Processing SDP '%s'", sdp.c_str() ); - - try - { - mSessDesc = new SessionDescriptor( mUrl, sdp ); - mFormatContext = mSessDesc->generateFormatContext(); - } - catch( const Exception &e ) - { - Error( e.getMessage().c_str() ); - return( -1 ); - } + try + { + mSessDesc = new SessionDescriptor( mUrl, sdp ); + mFormatContext = mSessDesc->generateFormatContext(); + } + catch( const Exception &e ) + { + Error( e.getMessage().c_str() ); + return( -1 ); + } #if 0 - // New method using ffmpeg native functions - std::string authUrl = mUrl; - if ( !mAuth.empty() ) - authUrl.insert( authUrl.find( "://" )+3, mAuth+"@" ); + // New method using ffmpeg native functions + std::string authUrl = mUrl; + if ( !mAuth.empty() ) + authUrl.insert( authUrl.find( "://" )+3, mAuth+"@" ); - if ( av_open_input_file( &mFormatContext, authUrl.c_str(), NULL, 0, NULL ) != 0 ) - { - Error( "Unable to open input '%s'", authUrl.c_str() ); - return( -1 ); - } + if ( av_open_input_file( &mFormatContext, authUrl.c_str(), NULL, 0, NULL ) != 0 ) + { + Error( "Unable to open input '%s'", authUrl.c_str() ); + return( -1 ); + } #endif - uint32_t rtpClock = 0; - std::string trackUrl = mUrl; - std::string controlUrl; - - _AVCODECID codecId; - - if ( mFormatContext->nb_streams >= 1 ) + uint32_t rtpClock = 0; + std::string trackUrl = mUrl; + std::string controlUrl; + + _AVCODECID codecId; + + if ( mFormatContext->nb_streams >= 1 ) + { + for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) { - for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) - { - SessionDescriptor::MediaDescriptor *mediaDesc = mSessDesc->getStream( i ); + SessionDescriptor::MediaDescriptor *mediaDesc = mSessDesc->getStream( i ); #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) + if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) #else - if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) + if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) #endif - { - // Check if control Url is absolute or relative - controlUrl = mediaDesc->getControlUrl(); - if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin())) - { - trackUrl = controlUrl; - } - else - { - if ( *trackUrl.rbegin() != '/') { - trackUrl += "/" + controlUrl; - } else { - trackUrl += controlUrl; - } - } - rtpClock = mediaDesc->getClock(); - codecId = mFormatContext->streams[i]->codec->codec_id; - // Hackery pokery - //rtpClock = mFormatContext->streams[i]->codec->sample_rate; - break; - } + { + // Check if control Url is absolute or relative + controlUrl = mediaDesc->getControlUrl(); + if (std::equal(trackUrl.begin(), trackUrl.end(), controlUrl.begin())) + { + trackUrl = controlUrl; } + else + { + if ( *trackUrl.rbegin() != '/') { + trackUrl += "/" + controlUrl; + } else { + trackUrl += controlUrl; + } + } + rtpClock = mediaDesc->getClock(); + codecId = mFormatContext->streams[i]->codec->codec_id; + // Hackery pokery + //rtpClock = mFormatContext->streams[i]->codec->sample_rate; + break; + } } + } - switch( mMethod ) + switch( mMethod ) + { + case RTP_UNICAST : { - case RTP_UNICAST : - { - localPorts[0] = requestPorts(); - localPorts[1] = localPorts[0]+1; + localPorts[0] = requestPorts(); + localPorts[1] = localPorts[0]+1; - message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP;unicast;client_port="+stringtf( "%d", localPorts[0] )+"-"+stringtf( "%d", localPorts[1] )+"\r\n"; - break; - } - case RTP_MULTICAST : - { - message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP;multicast\r\n"; - break; - } - case RTP_RTSP : - case RTP_RTSP_HTTP : - { - message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP/TCP;unicast\r\n"; - break; - } - default: - { - Panic( "Got unexpected method %d", mMethod ); - break; - } + message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP;unicast;client_port="+stringtf( "%d", localPorts[0] )+"-"+stringtf( "%d", localPorts[1] )+"\r\n"; + break; } - - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); - - lines = split( response, "\r\n" ); - std::string session; - int timeout = 0; - char transport[256] = ""; - - for ( size_t i = 0; i < lines.size(); i++ ) + case RTP_MULTICAST : { - if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) ) - { - StringVector sessionLine = split( lines[i].substr(9), ";" ); - session = trimSpaces( sessionLine[0] ); - if ( sessionLine.size() == 2 ) - sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout ); - } - sscanf( lines[i].c_str(), "Transport: %s", transport ); + message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP;multicast\r\n"; + break; } - - if ( session.empty() ) - Fatal( "Unable to get session identifier from response '%s'", response.c_str() ); - - Debug( 2, "Got RTSP session %s, timeout %d secs", session.c_str(), timeout ); - - if ( !transport[0] ) - Fatal( "Unable to get transport details from response '%s'", response.c_str() ); - - Debug( 2, "Got RTSP transport %s", transport ); - - std::string method = ""; - int remotePorts[2] = { 0, 0 }; - int remoteChannels[2] = { 0, 0 }; - std::string distribution = ""; - unsigned long ssrc = 0; - StringVector parts = split( transport, ";" ); - for ( size_t i = 0; i < parts.size(); i++ ) + case RTP_RTSP : + case RTP_RTSP_HTTP : { - if ( parts[i] == "unicast" || parts[i] == "multicast" ) - distribution = parts[i]; - else if ( startsWith( parts[i], "server_port=" ) ) - { - method = "RTP/UNICAST"; - StringVector subparts = split( parts[i], "=" ); - StringVector ports = split( subparts[1], "-" ); - remotePorts[0] = strtol( ports[0].c_str(), NULL, 10 ); - remotePorts[1] = strtol( ports[1].c_str(), NULL, 10 ); - } - else if ( startsWith( parts[i], "interleaved=" ) ) - { - method = "RTP/RTSP"; - StringVector subparts = split( parts[i], "=" ); - StringVector channels = split( subparts[1], "-" ); - remoteChannels[0] = strtol( channels[0].c_str(), NULL, 10 ); - remoteChannels[1] = strtol( channels[1].c_str(), NULL, 10 ); - } - else if ( startsWith( parts[i], "port=" ) ) - { - method = "RTP/MULTICAST"; - StringVector subparts = split( parts[i], "=" ); - StringVector ports = split( subparts[1], "-" ); - localPorts[0] = strtol( ports[0].c_str(), NULL, 10 ); - localPorts[1] = strtol( ports[1].c_str(), NULL, 10 ); - } - else if ( startsWith( parts[i], "destination=" ) ) - { - StringVector subparts = split( parts[i], "=" ); - localHost = subparts[1]; - } - else if ( startsWith( parts[i], "ssrc=" ) ) - { - StringVector subparts = split( parts[i], "=" ); - ssrc = strtoll( subparts[1].c_str(), NULL, 16 ); - } + message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP/TCP;unicast\r\n"; + break; } - - Debug( 2, "RTSP Method is %s", method.c_str() ); - Debug( 2, "RTSP Distribution is %s", distribution.c_str() ); - Debug( 2, "RTSP SSRC is %lx", ssrc ); - Debug( 2, "RTSP Local Host is %s", localHost.c_str() ); - Debug( 2, "RTSP Local Ports are %d/%d", localPorts[0], localPorts[1] ); - Debug( 2, "RTSP Remote Ports are %d/%d", remotePorts[0], remotePorts[1] ); - Debug( 2, "RTSP Remote Channels are %d/%d", remoteChannels[0], remoteChannels[1] ); - - message = "PLAY "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\nRange: npt=0.000-\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); - - lines = split( response, "\r\n" ); - std::string rtpInfo; - for ( size_t i = 0; i < lines.size(); i++ ) + default: { - if ( ( lines[i].size() > 9 ) && ( lines[i].substr( 0, 9 ) == "RTP-Info:" ) ) - rtpInfo = trimSpaces( lines[i].substr( 9 ) ); - // Check for a timeout again. Some rtsp devices don't send a timeout until after the PLAY command is sent - if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) ) + Panic( "Got unexpected method %d", mMethod ); + break; + } + } + + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + lines = split( response, "\r\n" ); + std::string session; + int timeout = 0; + char transport[256] = ""; + + for ( size_t i = 0; i < lines.size(); i++ ) + { + if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) ) + { + StringVector sessionLine = split( lines[i].substr(9), ";" ); + session = trimSpaces( sessionLine[0] ); + if ( sessionLine.size() == 2 ) + sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout ); + } + sscanf( lines[i].c_str(), "Transport: %s", transport ); + } + + if ( session.empty() ) + Fatal( "Unable to get session identifier from response '%s'", response.c_str() ); + + Debug( 2, "Got RTSP session %s, timeout %d secs", session.c_str(), timeout ); + + if ( !transport[0] ) + Fatal( "Unable to get transport details from response '%s'", response.c_str() ); + + Debug( 2, "Got RTSP transport %s", transport ); + + std::string method = ""; + int remotePorts[2] = { 0, 0 }; + int remoteChannels[2] = { 0, 0 }; + std::string distribution = ""; + unsigned long ssrc = 0; + StringVector parts = split( transport, ";" ); + for ( size_t i = 0; i < parts.size(); i++ ) + { + if ( parts[i] == "unicast" || parts[i] == "multicast" ) + distribution = parts[i]; + else if ( startsWith( parts[i], "server_port=" ) ) + { + method = "RTP/UNICAST"; + StringVector subparts = split( parts[i], "=" ); + StringVector ports = split( subparts[1], "-" ); + remotePorts[0] = strtol( ports[0].c_str(), NULL, 10 ); + remotePorts[1] = strtol( ports[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "interleaved=" ) ) + { + method = "RTP/RTSP"; + StringVector subparts = split( parts[i], "=" ); + StringVector channels = split( subparts[1], "-" ); + remoteChannels[0] = strtol( channels[0].c_str(), NULL, 10 ); + remoteChannels[1] = strtol( channels[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "port=" ) ) + { + method = "RTP/MULTICAST"; + StringVector subparts = split( parts[i], "=" ); + StringVector ports = split( subparts[1], "-" ); + localPorts[0] = strtol( ports[0].c_str(), NULL, 10 ); + localPorts[1] = strtol( ports[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "destination=" ) ) + { + StringVector subparts = split( parts[i], "=" ); + localHost = subparts[1]; + } + else if ( startsWith( parts[i], "ssrc=" ) ) + { + StringVector subparts = split( parts[i], "=" ); + ssrc = strtoll( subparts[1].c_str(), NULL, 16 ); + } + } + + Debug( 2, "RTSP Method is %s", method.c_str() ); + Debug( 2, "RTSP Distribution is %s", distribution.c_str() ); + Debug( 2, "RTSP SSRC is %lx", ssrc ); + Debug( 2, "RTSP Local Host is %s", localHost.c_str() ); + Debug( 2, "RTSP Local Ports are %d/%d", localPorts[0], localPorts[1] ); + Debug( 2, "RTSP Remote Ports are %d/%d", remotePorts[0], remotePorts[1] ); + Debug( 2, "RTSP Remote Channels are %d/%d", remoteChannels[0], remoteChannels[1] ); + + message = "PLAY "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\nRange: npt=0.000-\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + lines = split( response, "\r\n" ); + std::string rtpInfo; + for ( size_t i = 0; i < lines.size(); i++ ) + { + if ( ( lines[i].size() > 9 ) && ( lines[i].substr( 0, 9 ) == "RTP-Info:" ) ) + rtpInfo = trimSpaces( lines[i].substr( 9 ) ); + // Check for a timeout again. Some rtsp devices don't send a timeout until after the PLAY command is sent + if ( ( lines[i].size() > 8 ) && ( lines[i].substr( 0, 8 ) == "Session:" ) && ( timeout == 0 ) ) + { + StringVector sessionLine = split( lines[i].substr(9), ";" ); + if ( sessionLine.size() == 2 ) + sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout ); + if ( timeout > 0 ) + Debug( 2, "Got timeout %d secs from PLAY command response", timeout ); + } + } + + int seq = 0; + unsigned long rtpTime = 0; + StringVector streams; + if ( rtpInfo.empty() ) + { + Debug( 1, "RTP Info Empty. Starting values for Sequence and Rtptime shall be zero."); + } + else + { + Debug( 2, "Got RTP Info %s", rtpInfo.c_str() ); + // More than one stream can be included in the RTP Info + streams = split( rtpInfo.c_str(), "," ); + for ( size_t i = 0; i < streams.size(); i++ ) + { + // We want the stream that matches the trackUrl we are using + if ( streams[i].find(controlUrl.c_str()) != std::string::npos ) + { + // Parse the sequence and rtptime values + parts = split( streams[i].c_str(), ";" ); + for ( size_t j = 0; j < parts.size(); j++ ) { - StringVector sessionLine = split( lines[i].substr(9), ";" ); - if ( sessionLine.size() == 2 ) - sscanf( trimSpaces( sessionLine[1] ).c_str(), "timeout=%d", &timeout ); - if ( timeout > 0 ) - Debug( 2, "Got timeout %d secs from PLAY command response", timeout ); + if ( startsWith( parts[j], "seq=" ) ) + { + StringVector subparts = split( parts[j], "=" ); + seq = strtol( subparts[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[j], "rtptime=" ) ) + { + StringVector subparts = split( parts[j], "=" ); + rtpTime = strtol( subparts[1].c_str(), NULL, 10 ); + } } + break; + } } + } - int seq = 0; - unsigned long rtpTime = 0; - StringVector streams; - if ( rtpInfo.empty() ) + Debug( 2, "RTSP Seq is %d", seq ); + Debug( 2, "RTSP Rtptime is %ld", rtpTime ); + + time_t lastKeepalive = time(NULL); + time_t now; + message = "GET_PARAMETER "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + + switch( mMethod ) + { + case RTP_UNICAST : { - Debug( 1, "RTP Info Empty. Starting values for Sequence and Rtptime shall be zero."); - } - else - { - Debug( 2, "Got RTP Info %s", rtpInfo.c_str() ); - // More than one stream can be included in the RTP Info - streams = split( rtpInfo.c_str(), "," ); - for ( size_t i = 0; i < streams.size(); i++ ) - { - // We want the stream that matches the trackUrl we are using - if ( streams[i].find(controlUrl.c_str()) != std::string::npos ) - { - // Parse the sequence and rtptime values - parts = split( streams[i].c_str(), ";" ); - for ( size_t j = 0; j < parts.size(); j++ ) - { - if ( startsWith( parts[j], "seq=" ) ) - { - StringVector subparts = split( parts[j], "=" ); - seq = strtol( subparts[1].c_str(), NULL, 10 ); - } - else if ( startsWith( parts[j], "rtptime=" ) ) - { - StringVector subparts = split( parts[j], "=" ); - rtpTime = strtol( subparts[1].c_str(), NULL, 10 ); - } - } - break; - } - } - } + RtpSource *source = new RtpSource( mId, "", localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId ); + mSources[ssrc] = source; + RtpDataThread rtpDataThread( *this, *source ); + RtpCtrlThread rtpCtrlThread( *this, *source ); - Debug( 2, "RTSP Seq is %d", seq ); - Debug( 2, "RTSP Rtptime is %ld", rtpTime ); + rtpDataThread.start(); + rtpCtrlThread.start(); - time_t lastKeepalive = time(NULL); - time_t now; - message = "GET_PARAMETER "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - - switch( mMethod ) - { - case RTP_UNICAST : - { - RtpSource *source = new RtpSource( mId, "", localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId ); - mSources[ssrc] = source; - RtpDataThread rtpDataThread( *this, *source ); - RtpCtrlThread rtpCtrlThread( *this, *source ); - - rtpDataThread.start(); - rtpCtrlThread.start(); - - while( !mStop ) - { - now = time(NULL); - // Send a keepalive message if the server supports this feature and we are close to the timeout expiration + while( !mStop ) + { + now = time(NULL); + // Send a keepalive message if the server supports this feature and we are close to the timeout expiration Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepalive, timeout, now, lastKeepalive, (now-lastKeepalive) ); - if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) - { - if ( !sendCommand( message ) ) - return( -1 ); - lastKeepalive = now; - } - usleep( 100000 ); - } + if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) + { + if ( !sendCommand( message ) ) + return( -1 ); + lastKeepalive = now; + } + usleep( 100000 ); + } #if 0 - message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); + message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); #endif - message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); + message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); - rtpDataThread.stop(); - rtpCtrlThread.stop(); + rtpDataThread.stop(); + rtpCtrlThread.stop(); - //rtpDataThread.kill( SIGTERM ); - //rtpCtrlThread.kill( SIGTERM ); + //rtpDataThread.kill( SIGTERM ); + //rtpCtrlThread.kill( SIGTERM ); - rtpDataThread.join(); - rtpCtrlThread.join(); - - delete mSources[ssrc]; - mSources.clear(); + rtpDataThread.join(); + rtpCtrlThread.join(); + + delete mSources[ssrc]; + mSources.clear(); - releasePorts( localPorts[0] ); + releasePorts( localPorts[0] ); - break; - } - case RTP_RTSP : - case RTP_RTSP_HTTP : - { - RtpSource *source = new RtpSource( mId, "", remoteChannels[0], mHost, remoteChannels[0], ssrc, seq, rtpClock, rtpTime, codecId ); - mSources[ssrc] = source; - // These never actually run - RtpDataThread rtpDataThread( *this, *source ); - RtpCtrlThread rtpCtrlThread( *this, *source ); - - Select select( double(config.http_timeout)/1000.0 ); - select.addReader( &mRtspSocket ); - - Buffer buffer( ZM_NETWORK_BUFSIZ ); - std::string keepaliveMessage = "OPTIONS "+mUrl+" RTSP/1.0\r\n"; - std::string keepaliveResponse = "RTSP/1.0 200 OK\r\n"; - while ( !mStop && select.wait() >= 0 ) - { - Select::CommsList readable = select.getReadable(); - if ( readable.size() == 0 ) - { - Error( "RTSP timed out" ); - break; - } - - static char tempBuffer[ZM_NETWORK_BUFSIZ]; - ssize_t nBytes = mRtspSocket.recv( tempBuffer, sizeof(tempBuffer) ); - buffer.append( tempBuffer, nBytes ); - Debug( 4, "Read %zd bytes on sd %d, %d total", nBytes, mRtspSocket.getReadDesc(), buffer.size() ); - - while( buffer.size() > 0 ) - { - if ( buffer[0] == '$' ) - { - if ( buffer.size() < 4 ) - break; - unsigned char channel = buffer[1]; - unsigned short len = ntohs( *((unsigned short *)(buffer+2)) ); - - Debug( 4, "Got %d bytes left, expecting %d byte packet on channel %d", buffer.size(), len, channel ); - if ( (unsigned short)buffer.size() < (len+4) ) - { - Debug( 4, "Missing %d bytes, rereading", (len+4)-buffer.size() ); - break; - } - if ( channel == remoteChannels[0] ) - { - Debug( 4, "Got %d bytes on data channel %d, packet length is %d", buffer.size(), channel, len ); - Hexdump( 4, (char *)buffer, 16 ); - rtpDataThread.recvPacket( buffer+4, len ); - Debug( 4, "Received" ); - } - else if ( channel == remoteChannels[1] ) - { -// len = ntohs( *((unsigned short *)(buffer+2)) ); -// Debug( 4, "Got %d bytes on control channel %d", nBytes, channel ); - Debug( 4, "Got %d bytes on control channel %d, packet length is %d", buffer.size(), channel, len ); - Hexdump( 4, (char *)buffer, 16 ); - rtpCtrlThread.recvPackets( buffer+4, len ); - } - else - { - Error( "Unexpected channel selector %d in RTSP interleaved data", buffer[1] ); - buffer.clear(); - break; - } - buffer.consume( len+4 ); - nBytes -= len+4; - } - else - { - if ( keepaliveResponse.compare( 0, keepaliveResponse.size(), (char *)buffer, keepaliveResponse.size() ) == 0 ) - { - Debug( 4, "Got keepalive response '%s'", (char *)buffer ); - //buffer.consume( keepaliveResponse.size() ); - if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) - { - int discardBytes = charPtr-(char *)buffer; - buffer -= discardBytes; - } - else - { - buffer.clear(); - } - } - else - { - if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) - { - int discardBytes = charPtr-(char *)buffer; - Warning( "Unexpected format RTSP interleaved data, resyncing by %d bytes", discardBytes ); - Hexdump( -1, (char *)buffer, discardBytes ); - buffer -= discardBytes; - } - else - { - Warning( "Unexpected format RTSP interleaved data, dumping %d bytes", buffer.size() ); - Hexdump( -1, (char *)buffer, 32 ); - buffer.clear(); - } - } - } - } - // Send a keepalive message if the server supports this feature and we are close to the timeout expiration - // FIXME: Is this really necessary when using tcp ? - now = time(NULL); - // Send a keepalive message if the server supports this feature and we are close to the timeout expiration -Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepalive, timeout, now, lastKeepalive, (now-lastKeepalive) ); - if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) - { - if ( !sendCommand( message ) ) - return( -1 ); - lastKeepalive = now; - } - buffer.tidy( 1 ); - } -#if 0 - message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); -#endif - // Send a teardown message but don't expect a response as this may not be implemented on the server when using TCP - message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - - delete mSources[ssrc]; - mSources.clear(); - - break; - } - case RTP_MULTICAST : - { - RtpSource *source = new RtpSource( mId, localHost, localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId ); - mSources[ssrc] = source; - RtpDataThread rtpDataThread( *this, *source ); - RtpCtrlThread rtpCtrlThread( *this, *source ); - - rtpDataThread.start(); - rtpCtrlThread.start(); - - while( !mStop ) - { - // Send a keepalive message if the server supports this feature and we are close to the timeout expiration - if ( sendKeepalive && (timeout > 0) && ((time(NULL)-lastKeepalive) > (timeout-5)) ) - { - if ( !sendCommand( message ) ) - return( -1 ); - lastKeepalive = time(NULL); - } - usleep( 100000 ); - } -#if 0 - message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); -#endif - message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; - if ( !sendCommand( message ) ) - return( -1 ); - if ( !recvResponse( response ) ) - return( -1 ); - - rtpDataThread.stop(); - rtpCtrlThread.stop(); - - rtpDataThread.join(); - rtpCtrlThread.join(); - - delete mSources[ssrc]; - mSources.clear(); - - releasePorts( localPorts[0] ); - break; - } - default: - { - Panic( "Got unexpected method %d", mMethod ); - break; - } + break; } + case RTP_RTSP : + case RTP_RTSP_HTTP : + { + RtpSource *source = new RtpSource( mId, "", remoteChannels[0], mHost, remoteChannels[0], ssrc, seq, rtpClock, rtpTime, codecId ); + mSources[ssrc] = source; + // These never actually run + RtpDataThread rtpDataThread( *this, *source ); + RtpCtrlThread rtpCtrlThread( *this, *source ); - return( 0 ); + Select select( double(config.http_timeout)/1000.0 ); + select.addReader( &mRtspSocket ); + + Buffer buffer( ZM_NETWORK_BUFSIZ ); + std::string keepaliveMessage = "OPTIONS "+mUrl+" RTSP/1.0\r\n"; + std::string keepaliveResponse = "RTSP/1.0 200 OK\r\n"; + while ( !mStop && select.wait() >= 0 ) + { + Select::CommsList readable = select.getReadable(); + if ( readable.size() == 0 ) + { + Error( "RTSP timed out" ); + break; + } + + static char tempBuffer[ZM_NETWORK_BUFSIZ]; + ssize_t nBytes = mRtspSocket.recv( tempBuffer, sizeof(tempBuffer) ); + buffer.append( tempBuffer, nBytes ); + Debug( 4, "Read %zd bytes on sd %d, %d total", nBytes, mRtspSocket.getReadDesc(), buffer.size() ); + + while( buffer.size() > 0 ) + { + if ( buffer[0] == '$' ) + { + if ( buffer.size() < 4 ) + break; + unsigned char channel = buffer[1]; + unsigned short len = ntohs( *((unsigned short *)(buffer+2)) ); + + Debug( 4, "Got %d bytes left, expecting %d byte packet on channel %d", buffer.size(), len, channel ); + if ( (unsigned short)buffer.size() < (len+4) ) + { + Debug( 4, "Missing %d bytes, rereading", (len+4)-buffer.size() ); + break; + } + if ( channel == remoteChannels[0] ) + { + Debug( 4, "Got %d bytes on data channel %d, packet length is %d", buffer.size(), channel, len ); + Hexdump( 4, (char *)buffer, 16 ); + rtpDataThread.recvPacket( buffer+4, len ); + Debug( 4, "Received" ); + } + else if ( channel == remoteChannels[1] ) + { +// len = ntohs( *((unsigned short *)(buffer+2)) ); +// Debug( 4, "Got %d bytes on control channel %d", nBytes, channel ); + Debug( 4, "Got %d bytes on control channel %d, packet length is %d", buffer.size(), channel, len ); + Hexdump( 4, (char *)buffer, 16 ); + rtpCtrlThread.recvPackets( buffer+4, len ); + } + else + { + Error( "Unexpected channel selector %d in RTSP interleaved data", buffer[1] ); + buffer.clear(); + break; + } + buffer.consume( len+4 ); + nBytes -= len+4; + } + else + { + if ( keepaliveResponse.compare( 0, keepaliveResponse.size(), (char *)buffer, keepaliveResponse.size() ) == 0 ) + { + Debug( 4, "Got keepalive response '%s'", (char *)buffer ); + //buffer.consume( keepaliveResponse.size() ); + if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) + { + int discardBytes = charPtr-(char *)buffer; + buffer -= discardBytes; + } + else + { + buffer.clear(); + } + } + else + { + if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) + { + int discardBytes = charPtr-(char *)buffer; + Warning( "Unexpected format RTSP interleaved data, resyncing by %d bytes", discardBytes ); + Hexdump( -1, (char *)buffer, discardBytes ); + buffer -= discardBytes; + } + else + { + Warning( "Unexpected format RTSP interleaved data, dumping %d bytes", buffer.size() ); + Hexdump( -1, (char *)buffer, 32 ); + buffer.clear(); + } + } + } + } + // Send a keepalive message if the server supports this feature and we are close to the timeout expiration + // FIXME: Is this really necessary when using tcp ? + now = time(NULL); + // Send a keepalive message if the server supports this feature and we are close to the timeout expiration +Debug(5, "sendkeepalive %d, timeout %d, now: %d last: %d since: %d", sendKeepalive, timeout, now, lastKeepalive, (now-lastKeepalive) ); + if ( sendKeepalive && (timeout > 0) && ((now-lastKeepalive) > (timeout-5)) ) + { + if ( !sendCommand( message ) ) + return( -1 ); + lastKeepalive = now; + } + buffer.tidy( 1 ); + } +#if 0 + message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); +#endif + // Send a teardown message but don't expect a response as this may not be implemented on the server when using TCP + message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + + delete mSources[ssrc]; + mSources.clear(); + + break; + } + case RTP_MULTICAST : + { + RtpSource *source = new RtpSource( mId, localHost, localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime, codecId ); + mSources[ssrc] = source; + RtpDataThread rtpDataThread( *this, *source ); + RtpCtrlThread rtpCtrlThread( *this, *source ); + + rtpDataThread.start(); + rtpCtrlThread.start(); + + while( !mStop ) + { + // Send a keepalive message if the server supports this feature and we are close to the timeout expiration + if ( sendKeepalive && (timeout > 0) && ((time(NULL)-lastKeepalive) > (timeout-5)) ) + { + if ( !sendCommand( message ) ) + return( -1 ); + lastKeepalive = time(NULL); + } + usleep( 100000 ); + } +#if 0 + message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); +#endif + message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + rtpDataThread.stop(); + rtpCtrlThread.stop(); + + rtpDataThread.join(); + rtpCtrlThread.join(); + + delete mSources[ssrc]; + mSources.clear(); + + releasePorts( localPorts[0] ); + break; + } + default: + { + Panic( "Got unexpected method %d", mMethod ); + break; + } + } + + return( 0 ); } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtsp.h b/src/zm_rtsp.h index 192200d0b..bdd14da42 100644 --- a/src/zm_rtsp.h +++ b/src/zm_rtsp.h @@ -34,110 +34,110 @@ class RtspThread : public Thread { public: - typedef enum { RTP_UNICAST, RTP_MULTICAST, RTP_RTSP, RTP_RTSP_HTTP } RtspMethod; - typedef enum { UNDEFINED, UNICAST, MULTICAST } RtspDist; + typedef enum { RTP_UNICAST, RTP_MULTICAST, RTP_RTSP, RTP_RTSP_HTTP } RtspMethod; + typedef enum { UNDEFINED, UNICAST, MULTICAST } RtspDist; private: - typedef std::set PortSet; - typedef std::set SsrcSet; - typedef std::map SourceMap; + typedef std::set PortSet; + typedef std::set SsrcSet; + typedef std::map SourceMap; private: - static int smMinDataPort; - static int smMaxDataPort; - static PortSet smLocalSsrcs; - static PortSet smAssignedPorts; + static int smMinDataPort; + static int smMaxDataPort; + static PortSet smLocalSsrcs; + static PortSet smAssignedPorts; private: - int mId; + int mId; - RtspMethod mMethod; - std::string mProtocol; - std::string mHost; - std::string mPort; - std::string mPath; - bool mRtspDescribe; - std::string mUrl; - - // Reworked authentication system - // First try without authentication, even if we have a username and password - // on receiving a 401 response, select authentication method (basic or digest) - // fill required fields and set needAuth - // subsequent requests can set the required authentication header. - bool mNeedAuth; - int respCode; - zm::Authenticator* mAuthenticator; + RtspMethod mMethod; + std::string mProtocol; + std::string mHost; + std::string mPort; + std::string mPath; + bool mRtspDescribe; + std::string mUrl; + + // Reworked authentication system + // First try without authentication, even if we have a username and password + // on receiving a 401 response, select authentication method (basic or digest) + // fill required fields and set needAuth + // subsequent requests can set the required authentication header. + bool mNeedAuth; + int respCode; + zm::Authenticator* mAuthenticator; - std::string mHttpSession; ///< Only for RTSP over HTTP sessions + std::string mHttpSession; ///< Only for RTSP over HTTP sessions - TcpInetClient mRtspSocket; - TcpInetClient mRtspSocket2; + TcpInetClient mRtspSocket; + TcpInetClient mRtspSocket2; - SourceMap mSources; + SourceMap mSources; - SessionDescriptor *mSessDesc; - AVFormatContext *mFormatContext; + SessionDescriptor *mSessDesc; + AVFormatContext *mFormatContext; - uint16_t mSeq; - uint32_t mSession; - uint32_t mSsrc; + uint16_t mSeq; + uint32_t mSession; + uint32_t mSsrc; - int mRemotePorts[2]; - int mRemoteChannels[2]; - RtspDist mDist; + int mRemotePorts[2]; + int mRemoteChannels[2]; + RtspDist mDist; - unsigned long mRtpTime; + unsigned long mRtpTime; - bool mStop; + bool mStop; private: - bool sendCommand( std::string message ); - bool recvResponse( std::string &response ); - void checkAuthResponse(std::string &response); + bool sendCommand( std::string message ); + bool recvResponse( std::string &response ); + void checkAuthResponse(std::string &response); public: - RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth, bool rtsp_describe ); - ~RtspThread(); + RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth, bool rtsp_describe ); + ~RtspThread(); public: - int requestPorts(); - void releasePorts( int port ); + int requestPorts(); + void releasePorts( int port ); - bool isValidSsrc( uint32_t ssrc ); - bool updateSsrc( uint32_t ssrc, const RtpDataHeader *header ); + bool isValidSsrc( uint32_t ssrc ); + bool updateSsrc( uint32_t ssrc, const RtpDataHeader *header ); - uint32_t getSsrc() const - { - return( mSsrc ); - } + uint32_t getSsrc() const + { + return( mSsrc ); + } - bool hasSources() const - { - return( !mSources.empty() ); - } + bool hasSources() const + { + return( !mSources.empty() ); + } - AVFormatContext *getFormatContext() - { - return( mFormatContext ); - } - - bool getFrame( Buffer &frame ) - { - SourceMap::iterator iter = mSources.begin(); - if ( iter == mSources.end() ) - return( false ); - return( iter->second->getFrame( frame ) ); - } - int run(); - void stop() - { - mStop = true; - } - bool stopped() const - { - return( mStop ); - } + AVFormatContext *getFormatContext() + { + return( mFormatContext ); + } + + bool getFrame( Buffer &frame ) + { + SourceMap::iterator iter = mSources.begin(); + if ( iter == mSources.end() ) + return( false ); + return( iter->second->getFrame( frame ) ); + } + int run(); + void stop() + { + mStop = true; + } + bool stopped() const + { + return( mStop ); + } }; #endif // ZM_RTSP_H diff --git a/src/zm_rtsp_auth.cpp b/src/zm_rtsp_auth.cpp index 9521a81d1..4f816b64a 100644 --- a/src/zm_rtsp_auth.cpp +++ b/src/zm_rtsp_auth.cpp @@ -28,206 +28,206 @@ namespace zm { Authenticator::Authenticator(std::string &username, std::string password) { #ifdef HAVE_GCRYPT_H - // Special initialisation for libgcrypt - if ( !gcry_check_version( GCRYPT_VERSION ) ) - { - Fatal( "Unable to initialise libgcrypt" ); - } - gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); - gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); + // Special initialisation for libgcrypt + if ( !gcry_check_version( GCRYPT_VERSION ) ) + { + Fatal( "Unable to initialise libgcrypt" ); + } + gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); + gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); #endif // HAVE_GCRYPT_H - - fAuthMethod = AUTH_UNDEFINED; - fUsername = username; - fPassword = password; - nc = 1; - fCnonce = "0a4f113b"; + + fAuthMethod = AUTH_UNDEFINED; + fUsername = username; + fPassword = password; + nc = 1; + fCnonce = "0a4f113b"; } Authenticator::~Authenticator() { - reset(); + reset(); } void Authenticator::reset() { - fRealm.clear(); - fNonce.clear(); - fUsername.clear(); - fPassword.clear(); - fAuthMethod = AUTH_UNDEFINED; + fRealm.clear(); + fNonce.clear(); + fUsername.clear(); + fPassword.clear(); + fAuthMethod = AUTH_UNDEFINED; } void Authenticator::authHandleHeader(std::string headerData) { - const char* basic_match = "Basic "; - const char* digest_match = "Digest "; - size_t digest_match_len = strlen(digest_match); - - // Check if basic auth - if (strncasecmp(headerData.c_str(),basic_match,strlen(basic_match)) == 0) + const char* basic_match = "Basic "; + const char* digest_match = "Digest "; + size_t digest_match_len = strlen(digest_match); + + // Check if basic auth + if (strncasecmp(headerData.c_str(),basic_match,strlen(basic_match)) == 0) + { + fAuthMethod = AUTH_BASIC; + Debug( 2, "Set authMethod to Basic"); + } + // Check if digest auth + else if (strncasecmp( headerData.c_str(),digest_match,digest_match_len ) == 0) + { + fAuthMethod = AUTH_DIGEST; + Debug( 2, "Set authMethod to Digest"); + StringVector subparts = split(headerData.substr(digest_match_len, headerData.length() - digest_match_len), ","); + // subparts are key="value" + for ( size_t i = 0; i < subparts.size(); i++ ) { - fAuthMethod = AUTH_BASIC; - Debug( 2, "Set authMethod to Basic"); - } - // Check if digest auth - else if (strncasecmp( headerData.c_str(),digest_match,digest_match_len ) == 0) - { - fAuthMethod = AUTH_DIGEST; - Debug( 2, "Set authMethod to Digest"); - StringVector subparts = split(headerData.substr(digest_match_len, headerData.length() - digest_match_len), ","); - // subparts are key="value" - for ( size_t i = 0; i < subparts.size(); i++ ) - { - StringVector kvPair = split( trimSpaces( subparts[i] ), "=" ); - std::string key = trimSpaces( kvPair[0] ); - if (key == "realm") { - fRealm = trimSet( kvPair[1], "\""); - continue; - } - if (key == "nonce") { - fNonce = trimSet( kvPair[1], "\""); - continue; - } - if (key == "qop") { - fQop = trimSet( kvPair[1], "\""); - continue; - } - } - Debug( 2, "Auth data completed. User: %s, realm: %s, nonce: %s, qop: %s", username().c_str(), fRealm.c_str(), fNonce.c_str(), fQop.c_str() ); + StringVector kvPair = split( trimSpaces( subparts[i] ), "=" ); + std::string key = trimSpaces( kvPair[0] ); + if (key == "realm") { + fRealm = trimSet( kvPair[1], "\""); + continue; + } + if (key == "nonce") { + fNonce = trimSet( kvPair[1], "\""); + continue; + } + if (key == "qop") { + fQop = trimSet( kvPair[1], "\""); + continue; + } } + Debug( 2, "Auth data completed. User: %s, realm: %s, nonce: %s, qop: %s", username().c_str(), fRealm.c_str(), fNonce.c_str(), fQop.c_str() ); + } } std::string Authenticator::quote(std::string src) { - return replaceAll(replaceAll(src, "\\", "\\\\"), "\"", "\\\""); + return replaceAll(replaceAll(src, "\\", "\\\\"), "\"", "\\\""); } std::string Authenticator::getAuthHeader(std::string method, std::string uri) { - std::string result = "Authorization: "; - if (fAuthMethod == AUTH_BASIC) - { - result += "Basic " + base64Encode( username() + ":" + password() ); + std::string result = "Authorization: "; + if (fAuthMethod == AUTH_BASIC) + { + result += "Basic " + base64Encode( username() + ":" + password() ); + } + else if (fAuthMethod == AUTH_DIGEST) + { + result += std::string("Digest ") + + "username=\"" + quote(username()) + "\", realm=\"" + quote(realm()) + "\", " + + "nonce=\"" + quote(nonce()) + "\", uri=\"" + quote(uri) + "\""; + if ( ! fQop.empty() ) { + result += ", qop=" + fQop; + result += ", nc=" + stringtf("%08x",nc); + result += ", cnonce=\"" + fCnonce + "\""; } - else if (fAuthMethod == AUTH_DIGEST) - { - result += std::string("Digest ") + - "username=\"" + quote(username()) + "\", realm=\"" + quote(realm()) + "\", " + - "nonce=\"" + quote(nonce()) + "\", uri=\"" + quote(uri) + "\""; - if ( ! fQop.empty() ) { - result += ", qop=" + fQop; - result += ", nc=" + stringtf("%08x",nc); - result += ", cnonce=\"" + fCnonce + "\""; - } - result += ", response=\"" + computeDigestResponse(method, uri) + "\""; - result += ", algorithm=\"MD5\""; - - //Authorization: Digest username="zm", - // realm="NC-336PW-HD-1080P", - // nonce="de8859d97609a6fcc16eaba490dcfd80", - // uri="rtsp://10.192.16.8:554/live/0/h264.sdp", - // response="4092120557d3099a163bd51a0d59744d", - // algorithm=MD5, - // opaque="5ccc069c403ebaf9f0171e9517f40e41", - // qop="auth", - // cnonce="c8051140765877dc", - // nc=00000001 - - } - result += "\r\n"; - return result; + result += ", response=\"" + computeDigestResponse(method, uri) + "\""; + result += ", algorithm=\"MD5\""; + + //Authorization: Digest username="zm", + // realm="NC-336PW-HD-1080P", + // nonce="de8859d97609a6fcc16eaba490dcfd80", + // uri="rtsp://10.192.16.8:554/live/0/h264.sdp", + // response="4092120557d3099a163bd51a0d59744d", + // algorithm=MD5, + // opaque="5ccc069c403ebaf9f0171e9517f40e41", + // qop="auth", + // cnonce="c8051140765877dc", + // nc=00000001 + + } + result += "\r\n"; + return result; } std::string Authenticator::computeDigestResponse(std::string &method, std::string &uri) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT - // The "response" field is computed as: - // md5(md5(::)::md5(:)) - size_t md5len = 16; - unsigned char md5buf[md5len]; - char md5HexBuf[md5len*2+1]; - - // Step 1: md5(::) - std::string ha1Data = username() + ":" + realm() + ":" + password(); - Debug( 2, "HA1 pre-md5: %s", ha1Data.c_str() ); + // The "response" field is computed as: + // md5(md5(::)::md5(:)) + size_t md5len = 16; + unsigned char md5buf[md5len]; + char md5HexBuf[md5len*2+1]; + + // Step 1: md5(::) + std::string ha1Data = username() + ":" + realm() + ":" + password(); + Debug( 2, "HA1 pre-md5: %s", ha1Data.c_str() ); #if HAVE_DECL_MD5 - MD5((unsigned char*)ha1Data.c_str(), ha1Data.length(), md5buf); + MD5((unsigned char*)ha1Data.c_str(), ha1Data.length(), md5buf); #elif HAVE_DECL_GNUTLS_FINGERPRINT - gnutls_datum_t md5dataha1 = { (unsigned char*)ha1Data.c_str(), ha1Data.length() }; - gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len ); + gnutls_datum_t md5dataha1 = { (unsigned char*)ha1Data.c_str(), ha1Data.length() }; + gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len ); #endif - for ( unsigned int j = 0; j < md5len; j++ ) - { - sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] ); - } - md5HexBuf[md5len*2]='\0'; - std::string ha1Hash = md5HexBuf; - - // Step 2: md5(:) - std::string ha2Data = method + ":" + uri; - Debug( 2, "HA2 pre-md5: %s", ha2Data.c_str() ); + for ( unsigned int j = 0; j < md5len; j++ ) + { + sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] ); + } + md5HexBuf[md5len*2]='\0'; + std::string ha1Hash = md5HexBuf; + + // Step 2: md5(:) + std::string ha2Data = method + ":" + uri; + Debug( 2, "HA2 pre-md5: %s", ha2Data.c_str() ); #if HAVE_DECL_MD5 - MD5((unsigned char*)ha2Data.c_str(), ha2Data.length(), md5buf ); + MD5((unsigned char*)ha2Data.c_str(), ha2Data.length(), md5buf ); #elif HAVE_DECL_GNUTLS_FINGERPRINT - gnutls_datum_t md5dataha2 = { (unsigned char*)ha2Data.c_str(), ha2Data.length() }; - gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len ); + gnutls_datum_t md5dataha2 = { (unsigned char*)ha2Data.c_str(), ha2Data.length() }; + gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len ); #endif - for ( unsigned int j = 0; j < md5len; j++ ) - { - sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); - } - md5HexBuf[md5len*2]='\0'; - std::string ha2Hash = md5HexBuf; + for ( unsigned int j = 0; j < md5len; j++ ) + { + sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); + } + md5HexBuf[md5len*2]='\0'; + std::string ha2Hash = md5HexBuf; - // Step 3: md5(ha1::ha2) - std::string digestData = ha1Hash + ":" + nonce(); - if ( ! fQop.empty() ) { - digestData += ":" + stringtf("%08x", nc) + ":"+fCnonce + ":" + fQop; - nc ++; - // if qop was specified, then we have to include t and a cnonce and an nccount - } - digestData += ":" + ha2Hash; - Debug( 2, "pre-md5: %s", digestData.c_str() ); + // Step 3: md5(ha1::ha2) + std::string digestData = ha1Hash + ":" + nonce(); + if ( ! fQop.empty() ) { + digestData += ":" + stringtf("%08x", nc) + ":"+fCnonce + ":" + fQop; + nc ++; + // if qop was specified, then we have to include t and a cnonce and an nccount + } + digestData += ":" + ha2Hash; + Debug( 2, "pre-md5: %s", digestData.c_str() ); #if HAVE_DECL_MD5 - MD5((unsigned char*)digestData.c_str(), digestData.length(), md5buf); + MD5((unsigned char*)digestData.c_str(), digestData.length(), md5buf); #elif HAVE_DECL_GNUTLS_FINGERPRINT - gnutls_datum_t md5datadigest = { (unsigned char*)digestData.c_str(), digestData.length() }; - gnutls_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len ); + gnutls_datum_t md5datadigest = { (unsigned char*)digestData.c_str(), digestData.length() }; + gnutls_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len ); #endif - for ( unsigned int j = 0; j < md5len; j++ ) - { - sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); - } - md5HexBuf[md5len*2]='\0'; + for ( unsigned int j = 0; j < md5len; j++ ) + { + sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); + } + md5HexBuf[md5len*2]='\0'; - return md5HexBuf; + return md5HexBuf; #else // HAVE_DECL_MD5 - Error( "You need to build with gnutls or openssl installed to use digest authentication" ); - return( 0 ); + Error( "You need to build with gnutls or openssl installed to use digest authentication" ); + return( 0 ); #endif // HAVE_DECL_MD5 } void Authenticator::checkAuthResponse(std::string &response) { - std::string authLine; - StringVector lines = split( response, "\r\n" ); - const char* authenticate_match = "WWW-Authenticate:"; - size_t authenticate_match_len = strlen(authenticate_match); + std::string authLine; + StringVector lines = split( response, "\r\n" ); + const char* authenticate_match = "WWW-Authenticate:"; + size_t authenticate_match_len = strlen(authenticate_match); - for ( size_t i = 0; i < lines.size(); i++ ) { - // stop at end of headers - if (lines[i].length()==0) - break; + for ( size_t i = 0; i < lines.size(); i++ ) { + // stop at end of headers + if (lines[i].length()==0) + break; - if (strncasecmp(lines[i].c_str(),authenticate_match,authenticate_match_len) == 0) { - authLine = lines[i]; - Debug( 2, "Found auth line at %d", i); - break; - } - } - if (!authLine.empty()) { - Debug( 2, "Analyze auth line %s", authLine.c_str()); - authHandleHeader( trimSpaces(authLine.substr(authenticate_match_len,authLine.length()-authenticate_match_len)) ); - } else { - Debug( 2, "Didn't find auth line in %s", authLine.c_str()); - } + if (strncasecmp(lines[i].c_str(),authenticate_match,authenticate_match_len) == 0) { + authLine = lines[i]; + Debug( 2, "Found auth line at %d", i); + break; + } + } + if (!authLine.empty()) { + Debug( 2, "Analyze auth line %s", authLine.c_str()); + authHandleHeader( trimSpaces(authLine.substr(authenticate_match_len,authLine.length()-authenticate_match_len)) ); + } else { + Debug( 2, "Didn't find auth line in %s", authLine.c_str()); + } } } // namespace zm diff --git a/src/zm_rtsp_auth.h b/src/zm_rtsp_auth.h index 079dec639..9249a15e2 100644 --- a/src/zm_rtsp_auth.h +++ b/src/zm_rtsp_auth.h @@ -37,20 +37,20 @@ namespace zm { enum AuthMethod { AUTH_UNDEFINED = 0, AUTH_BASIC = 1, AUTH_DIGEST = 2 }; class Authenticator { public: - Authenticator(std::string &username, std::string password); - virtual ~Authenticator(); - void reset(); + Authenticator(std::string &username, std::string password); + virtual ~Authenticator(); + void reset(); - std::string realm() { return fRealm; } - std::string nonce() { return fNonce; } - std::string username() { return fUsername; } - AuthMethod auth_method() const { return fAuthMethod; } - - std::string computeDigestResponse( std::string &cmd, std::string &url ); - void authHandleHeader( std::string headerData ); - std::string getAuthHeader( std::string method, std::string path ); - void checkAuthResponse(std::string &response); - + std::string realm() { return fRealm; } + std::string nonce() { return fNonce; } + std::string username() { return fUsername; } + AuthMethod auth_method() const { return fAuthMethod; } + + std::string computeDigestResponse( std::string &cmd, std::string &url ); + void authHandleHeader( std::string headerData ); + std::string getAuthHeader( std::string method, std::string path ); + void checkAuthResponse(std::string &response); + private: std::string password() { return fPassword; } AuthMethod fAuthMethod; @@ -61,7 +61,7 @@ private: std::string fUsername; std::string fPassword; std::string quote( std::string src ); - int nc; + int nc; }; } // namespace zm diff --git a/src/zm_sdp.cpp b/src/zm_sdp.cpp index dbc63a82f..7bfc4b1f9 100644 --- a/src/zm_sdp.cpp +++ b/src/zm_sdp.cpp @@ -25,489 +25,489 @@ #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { - { 0, "PCMU", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_MULAW, 8000, 1 }, - { 3, "GSM", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 4, "G723", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 5, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 6, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 16000, 1 }, - { 7, "LPC", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 8, "PCMA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_ALAW, 8000, 1 }, - { 9, "G722", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 10, "L16", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_S16BE, 44100, 2 }, - { 11, "L16", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_S16BE, 44100, 1 }, - { 12, "QCELP", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_QCELP, 8000, 1 }, - { 13, "CN", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 14, "MPA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP2, -1, -1 }, - { 14, "MPA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3, -1, -1 }, - { 15, "G728", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 16, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 11025, 1 }, - { 17, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 22050, 1 }, - { 18, "G729", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, - { 25, "CelB", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, - { 26, "JPEG", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MJPEG, 90000, -1 }, - { 28, "nv", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, - { 31, "H261", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H261, 90000, -1 }, - { 32, "MPV", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG1VIDEO, 90000, -1 }, - { 32, "MPV", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO, 90000, -1 }, - { 33, "MP2T", AVMEDIA_TYPE_DATA, AV_CODEC_ID_MPEG2TS, 90000, -1 }, - { 34, "H263", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H263, 90000, -1 }, - { -1, "", AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1 } + { 0, "PCMU", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_MULAW, 8000, 1 }, + { 3, "GSM", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 4, "G723", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 5, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 6, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 16000, 1 }, + { 7, "LPC", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 8, "PCMA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_ALAW, 8000, 1 }, + { 9, "G722", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 10, "L16", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_S16BE, 44100, 2 }, + { 11, "L16", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_PCM_S16BE, 44100, 1 }, + { 12, "QCELP", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_QCELP, 8000, 1 }, + { 13, "CN", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 14, "MPA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP2, -1, -1 }, + { 14, "MPA", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_MP3, -1, -1 }, + { 15, "G728", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 16, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 11025, 1 }, + { 17, "DVI4", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 22050, 1 }, + { 18, "G729", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_NONE, 8000, 1 }, + { 25, "CelB", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, + { 26, "JPEG", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MJPEG, 90000, -1 }, + { 28, "nv", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_NONE, 90000, -1 }, + { 31, "H261", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H261, 90000, -1 }, + { 32, "MPV", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG1VIDEO, 90000, -1 }, + { 32, "MPV", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG2VIDEO, 90000, -1 }, + { 33, "MP2T", AVMEDIA_TYPE_DATA, AV_CODEC_ID_MPEG2TS, 90000, -1 }, + { 34, "H263", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H263, 90000, -1 }, + { -1, "", AVMEDIA_TYPE_UNKNOWN, AV_CODEC_ID_NONE, -1, -1 } }; SessionDescriptor::DynamicPayloadDesc SessionDescriptor::smDynamicPayloads[] = { - { "MP4V-ES", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, - { "mpeg4-generic", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, - { "H264", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, - { "AMR", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AMR_NB }, - { "vnd.onvif.metadata", AVMEDIA_TYPE_DATA, AV_CODEC_ID_NONE } + { "MP4V-ES", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_MPEG4 }, + { "mpeg4-generic", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AAC }, + { "H264", AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_H264 }, + { "AMR", AVMEDIA_TYPE_AUDIO, AV_CODEC_ID_AMR_NB }, + { "vnd.onvif.metadata", AVMEDIA_TYPE_DATA, AV_CODEC_ID_NONE } }; #else SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { - { 0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8001, 1 }, - { 3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 4, "G723", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 5, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 6, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1 }, - { 7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 8, "PCMA", CODEC_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1 }, - { 9, "G722", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 10, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2 }, - { 11, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1 }, - { 12, "QCELP", CODEC_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1 }, - { 13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP2, -1, -1 }, - { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP3, -1, -1 }, - { 15, "G728", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 16, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 11025, 1 }, - { 17, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 22050, 1 }, - { 18, "G729", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, - { 25, "CelB", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, - { 26, "JPEG", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1 }, - { 28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, - { 31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1 }, - { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1 }, - { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, 90000, -1 }, - { 33, "MP2T", CODEC_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1 }, - { 34, "H263", CODEC_TYPE_VIDEO, CODEC_ID_H263, 90000, -1 }, - { -1, "", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1 } + { 0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8001, 1 }, + { 3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 4, "G723", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 5, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 6, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1 }, + { 7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 8, "PCMA", CODEC_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1 }, + { 9, "G722", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 10, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2 }, + { 11, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1 }, + { 12, "QCELP", CODEC_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1 }, + { 13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP2, -1, -1 }, + { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP3, -1, -1 }, + { 15, "G728", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 16, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 11025, 1 }, + { 17, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 22050, 1 }, + { 18, "G729", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 25, "CelB", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 26, "JPEG", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1 }, + { 28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1 }, + { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1 }, + { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, 90000, -1 }, + { 33, "MP2T", CODEC_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1 }, + { 34, "H263", CODEC_TYPE_VIDEO, CODEC_ID_H263, 90000, -1 }, + { -1, "", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1 } }; SessionDescriptor::DynamicPayloadDesc SessionDescriptor::smDynamicPayloads[] = { - { "MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4 }, - { "mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC }, - { "H264", CODEC_TYPE_VIDEO, CODEC_ID_H264 }, - { "AMR", CODEC_TYPE_AUDIO, CODEC_ID_AMR_NB }, - { "vnd.onvif.metadata", CODEC_TYPE_DATA, CODEC_ID_NONE } + { "MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4 }, + { "mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC }, + { "H264", CODEC_TYPE_VIDEO, CODEC_ID_H264 }, + { "AMR", CODEC_TYPE_AUDIO, CODEC_ID_AMR_NB }, + { "vnd.onvif.metadata", CODEC_TYPE_DATA, CODEC_ID_NONE } }; #endif SessionDescriptor::ConnInfo::ConnInfo( const std::string &connInfo ) : - mTtl( 16 ), - mNoAddresses( 0 ) + mTtl( 16 ), + mNoAddresses( 0 ) { - StringVector tokens = split( connInfo, " " ); - if ( tokens.size() < 3 ) - throw Exception( "Unable to parse SDP connection info from '"+connInfo+"'" ); - mNetworkType = tokens[0]; - if ( mNetworkType != "IN" ) - throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" ); - mAddressType = tokens[1]; - if ( mAddressType != "IP4" ) - throw Exception( "Invalid SDP address type '"+mAddressType+"' in connection info '"+connInfo+"'" ); - StringVector addressTokens = split( tokens[2], "/" ); - if ( addressTokens.size() < 1 ) - throw Exception( "Invalid SDP address '"+tokens[2]+"' in connection info '"+connInfo+"'" ); - mAddress = addressTokens[0]; - if ( addressTokens.size() >= 2 ) - mTtl = atoi(addressTokens[1].c_str()); - if ( addressTokens.size() >= 3 ) - mNoAddresses = atoi(addressTokens[2].c_str()); + StringVector tokens = split( connInfo, " " ); + if ( tokens.size() < 3 ) + throw Exception( "Unable to parse SDP connection info from '"+connInfo+"'" ); + mNetworkType = tokens[0]; + if ( mNetworkType != "IN" ) + throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" ); + mAddressType = tokens[1]; + if ( mAddressType != "IP4" ) + throw Exception( "Invalid SDP address type '"+mAddressType+"' in connection info '"+connInfo+"'" ); + StringVector addressTokens = split( tokens[2], "/" ); + if ( addressTokens.size() < 1 ) + throw Exception( "Invalid SDP address '"+tokens[2]+"' in connection info '"+connInfo+"'" ); + mAddress = addressTokens[0]; + if ( addressTokens.size() >= 2 ) + mTtl = atoi(addressTokens[1].c_str()); + if ( addressTokens.size() >= 3 ) + mNoAddresses = atoi(addressTokens[2].c_str()); } SessionDescriptor::BandInfo::BandInfo( const std::string &bandInfo ) : - mValue( 0 ) + mValue( 0 ) { - StringVector tokens = split( bandInfo, ":" ); - if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP bandwidth info from '"+bandInfo+"'" ); - mType = tokens[0]; - //if ( mNetworkType != "IN" ) - //throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" ); - mValue = atoi(tokens[1].c_str()); + StringVector tokens = split( bandInfo, ":" ); + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP bandwidth info from '"+bandInfo+"'" ); + mType = tokens[0]; + //if ( mNetworkType != "IN" ) + //throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" ); + mValue = atoi(tokens[1].c_str()); } SessionDescriptor::MediaDescriptor::MediaDescriptor( const std::string &type, int port, int numPorts, const std::string &transport, int payloadType ) : - mType( type ), - mPort( port ), - mNumPorts( numPorts ), - mTransport( transport ), - mPayloadType( payloadType ), - mFrameRate( 0.0 ), - mClock( 0 ), - mWidth( 0 ), - mHeight( 0 ), - mSprops( "" ), - mConnInfo( 0 ) + mType( type ), + mPort( port ), + mNumPorts( numPorts ), + mTransport( transport ), + mPayloadType( payloadType ), + mFrameRate( 0.0 ), + mClock( 0 ), + mWidth( 0 ), + mHeight( 0 ), + mSprops( "" ), + mConnInfo( 0 ) { } SessionDescriptor::SessionDescriptor( const std::string &url, const std::string &sdp ) : - mUrl( url ), - mConnInfo( 0 ), - mBandInfo( 0 ) + mUrl( url ), + mConnInfo( 0 ), + mBandInfo( 0 ) { - MediaDescriptor *currMedia = 0; + MediaDescriptor *currMedia = 0; - StringVector lines = split( sdp, "\r\n" ); - for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); iter++ ) + StringVector lines = split( sdp, "\r\n" ); + for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); iter++ ) + { + std::string line = *iter; + if ( line.empty() ) + break; + + Debug( 3, "Processing SDP line '%s'", line.c_str() ); + const char sdpType = line[0]; + if ( line[1] != '=' ) + throw Exception( "Invalid SDP format at '"+line+"'" ); + + line.erase( 0, 2 ); + switch( sdpType ) { - std::string line = *iter; - if ( line.empty() ) - break; - - Debug( 3, "Processing SDP line '%s'", line.c_str() ); - const char sdpType = line[0]; - if ( line[1] != '=' ) - throw Exception( "Invalid SDP format at '"+line+"'" ); - - line.erase( 0, 2 ); - switch( sdpType ) + case 'v' : + mVersion = line; + break; + case 'o' : + mOwner = line; + break; + case 's' : + mName = line; + break; + case 'i' : + mInfo = line; + break; + case 'c' : + // This prevent a memory leak if the field appears more than one time + if ( mConnInfo ) + delete mConnInfo; + mConnInfo = new ConnInfo( line ); + break; + case 'b' : + // This prevent a memory leak if the field appears more than one time + if ( mBandInfo ) + delete mBandInfo; + mBandInfo = new BandInfo( line ); + break; + case 't' : + mTimeInfo = line; + break; + case 'a' : + { + mAttributes.push_back( line ); + StringVector tokens = split( line, ":", 2 ); + std::string attrName = tokens[0]; + if ( currMedia ) { - case 'v' : - mVersion = line; - break; - case 'o' : - mOwner = line; - break; - case 's' : - mName = line; - break; - case 'i' : - mInfo = line; - break; - case 'c' : - // This prevent a memory leak if the field appears more than one time - if ( mConnInfo ) - delete mConnInfo; - mConnInfo = new ConnInfo( line ); - break; - case 'b' : - // This prevent a memory leak if the field appears more than one time - if ( mBandInfo ) - delete mBandInfo; - mBandInfo = new BandInfo( line ); - break; - case 't' : - mTimeInfo = line; - break; - case 'a' : + if ( attrName == "control" ) + { + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP control attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + currMedia->setControlUrl( tokens[1] ); + } + else if ( attrName == "range" ) + { + } + else if ( attrName == "rtpmap" ) + { + // a=rtpmap:96 MP4V-ES/90000 + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP rtpmap attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + StringVector attrTokens = split( tokens[1], " " ); + int payloadType = atoi(attrTokens[0].c_str()); + if ( payloadType != currMedia->getPayloadType() ) + throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + std::string payloadDesc = attrTokens[1]; + //currMedia->setPayloadType( payloadType ); + if ( attrTokens.size() > 1 ) { - mAttributes.push_back( line ); - StringVector tokens = split( line, ":", 2 ); - std::string attrName = tokens[0]; - if ( currMedia ) - { - if ( attrName == "control" ) - { - if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP control attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - currMedia->setControlUrl( tokens[1] ); - } - else if ( attrName == "range" ) - { - } - else if ( attrName == "rtpmap" ) - { - // a=rtpmap:96 MP4V-ES/90000 - if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP rtpmap attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - StringVector attrTokens = split( tokens[1], " " ); - int payloadType = atoi(attrTokens[0].c_str()); - if ( payloadType != currMedia->getPayloadType() ) - throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); - std::string payloadDesc = attrTokens[1]; - //currMedia->setPayloadType( payloadType ); - if ( attrTokens.size() > 1 ) - { - StringVector payloadTokens = split( attrTokens[1], "/" ); - std::string payloadDesc = payloadTokens[0]; - int payloadClock = atoi(payloadTokens[1].c_str()); - currMedia->setPayloadDesc( payloadDesc ); - currMedia->setClock( payloadClock ); - } - } - else if ( attrName == "framesize" ) - { - // a=framesize:96 320-240 - if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP framesize attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - StringVector attrTokens = split( tokens[1], " " ); - int payloadType = atoi(attrTokens[0].c_str()); - if ( payloadType != currMedia->getPayloadType() ) - throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); - //currMedia->setPayloadType( payloadType ); - StringVector sizeTokens = split( attrTokens[1], "-" ); - int width = atoi(sizeTokens[0].c_str()); - int height = atoi(sizeTokens[1].c_str()); - currMedia->setFrameSize( width, height ); - } - else if ( attrName == "framerate" ) - { - // a=framerate:5.0 - if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP framerate attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - double frameRate = atof(tokens[1].c_str()); - currMedia->setFrameRate( frameRate ); - } - else if ( attrName == "fmtp" ) - { - // a=fmtp:96 profile-level-id=247; config=000001B0F7000001B509000001000000012008D48D8803250F042D14440F - if ( tokens.size() < 2 ) - throw Exception( "Unable to parse SDP fmtp attribute '"+line+"' for media '"+currMedia->getType()+"'" ); - StringVector attrTokens = split( tokens[1], " ", 2 ); - int payloadType = atoi(attrTokens[0].c_str()); - if ( payloadType != currMedia->getPayloadType() ) - throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); - //currMedia->setPayloadType( payloadType ); - if ( attrTokens.size() > 1 ) - { - StringVector attr2Tokens = split( attrTokens[1], "; " ); - for ( unsigned int i = 0; i < attr2Tokens.size(); i++ ) - { - StringVector attr3Tokens = split( attr2Tokens[i], "=" ); - //Info( "Name = %s, Value = %s", attr3Tokens[0].c_str(), attr3Tokens[1].c_str() ); - if ( attr3Tokens[0] == "profile-level-id" ) - { - } - else if ( attr3Tokens[0] == "config" ) - { - } - else if ( attr3Tokens[0] == "sprop-parameter-sets" ) - { - size_t t = attr2Tokens[i].find("="); - char *c = (char *)attr2Tokens[i].c_str() + t + 1; - Debug(4, "sprop-parameter-sets value %s", c); - currMedia->setSprops(std::string(c)); - } - else if ( attr3Tokens[0] == "sprop-parameter-sets" ) - { - size_t t = attr2Tokens[i].find("="); - char *c = (char *)attr2Tokens[i].c_str() + t + 1; - Debug(4, "sprop-parameter-sets value %s", c); - currMedia->setSprops(std::string(c)); - } - else - { - Debug( 3, "Ignoring SDP fmtp attribute '%s' for media '%s'", attr3Tokens[0].c_str(), currMedia->getType().c_str() ) - } - } - } - } - else if ( attrName == "mpeg4-iod" ) - { - // a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA" - } - else if ( attrName == "mpeg4-esid" ) - { - // a=mpeg4-esid:201 - } - else - { - Debug( 3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str() ) - } - } - else - { - Debug( 3, "Ignoring general SDP attribute '%s'", line.c_str() ); - } - break; + StringVector payloadTokens = split( attrTokens[1], "/" ); + std::string payloadDesc = payloadTokens[0]; + int payloadClock = atoi(payloadTokens[1].c_str()); + currMedia->setPayloadDesc( payloadDesc ); + currMedia->setClock( payloadClock ); } - case 'm' : + } + else if ( attrName == "framesize" ) + { + // a=framesize:96 320-240 + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP framesize attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + StringVector attrTokens = split( tokens[1], " " ); + int payloadType = atoi(attrTokens[0].c_str()); + if ( payloadType != currMedia->getPayloadType() ) + throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + //currMedia->setPayloadType( payloadType ); + StringVector sizeTokens = split( attrTokens[1], "-" ); + int width = atoi(sizeTokens[0].c_str()); + int height = atoi(sizeTokens[1].c_str()); + currMedia->setFrameSize( width, height ); + } + else if ( attrName == "framerate" ) + { + // a=framerate:5.0 + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP framerate attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + double frameRate = atof(tokens[1].c_str()); + currMedia->setFrameRate( frameRate ); + } + else if ( attrName == "fmtp" ) + { + // a=fmtp:96 profile-level-id=247; config=000001B0F7000001B509000001000000012008D48D8803250F042D14440F + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP fmtp attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + StringVector attrTokens = split( tokens[1], " ", 2 ); + int payloadType = atoi(attrTokens[0].c_str()); + if ( payloadType != currMedia->getPayloadType() ) + throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + //currMedia->setPayloadType( payloadType ); + if ( attrTokens.size() > 1 ) { - StringVector tokens = split( line, " " ); - if ( tokens.size() < 4 ) - throw Exception( "Can't parse SDP media description '"+line+"'" ); - std::string mediaType = tokens[0]; - if ( mediaType != "audio" && mediaType != "video" && mediaType != "application" ) - throw Exception( "Unsupported media type '"+mediaType+"' in SDP media attribute '"+line+"'" ); - StringVector portTokens = split( tokens[1], "/" ); - int mediaPort = atoi(portTokens[0].c_str()); - int mediaNumPorts = 1; - if ( portTokens.size() > 1 ) - mediaNumPorts = atoi(portTokens[1].c_str()); - std::string mediaTransport = tokens[2]; - if ( mediaTransport != "RTP/AVP" ) - throw Exception( "Unsupported media transport '"+mediaTransport+"' in SDP media attribute '"+line+"'" ); - int payloadType = atoi(tokens[3].c_str()); - currMedia = new MediaDescriptor( mediaType, mediaPort, mediaNumPorts, mediaTransport, payloadType ); - mMediaList.push_back( currMedia ); - break; + StringVector attr2Tokens = split( attrTokens[1], "; " ); + for ( unsigned int i = 0; i < attr2Tokens.size(); i++ ) + { + StringVector attr3Tokens = split( attr2Tokens[i], "=" ); + //Info( "Name = %s, Value = %s", attr3Tokens[0].c_str(), attr3Tokens[1].c_str() ); + if ( attr3Tokens[0] == "profile-level-id" ) + { + } + else if ( attr3Tokens[0] == "config" ) + { + } + else if ( attr3Tokens[0] == "sprop-parameter-sets" ) + { + size_t t = attr2Tokens[i].find("="); + char *c = (char *)attr2Tokens[i].c_str() + t + 1; + Debug(4, "sprop-parameter-sets value %s", c); + currMedia->setSprops(std::string(c)); + } + else if ( attr3Tokens[0] == "sprop-parameter-sets" ) + { + size_t t = attr2Tokens[i].find("="); + char *c = (char *)attr2Tokens[i].c_str() + t + 1; + Debug(4, "sprop-parameter-sets value %s", c); + currMedia->setSprops(std::string(c)); + } + else + { + Debug( 3, "Ignoring SDP fmtp attribute '%s' for media '%s'", attr3Tokens[0].c_str(), currMedia->getType().c_str() ) + } + } } + } + else if ( attrName == "mpeg4-iod" ) + { + // a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA" + } + else if ( attrName == "mpeg4-esid" ) + { + // a=mpeg4-esid:201 + } + else + { + Debug( 3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str() ) + } } + else + { + Debug( 3, "Ignoring general SDP attribute '%s'", line.c_str() ); + } + break; + } + case 'm' : + { + StringVector tokens = split( line, " " ); + if ( tokens.size() < 4 ) + throw Exception( "Can't parse SDP media description '"+line+"'" ); + std::string mediaType = tokens[0]; + if ( mediaType != "audio" && mediaType != "video" && mediaType != "application" ) + throw Exception( "Unsupported media type '"+mediaType+"' in SDP media attribute '"+line+"'" ); + StringVector portTokens = split( tokens[1], "/" ); + int mediaPort = atoi(portTokens[0].c_str()); + int mediaNumPorts = 1; + if ( portTokens.size() > 1 ) + mediaNumPorts = atoi(portTokens[1].c_str()); + std::string mediaTransport = tokens[2]; + if ( mediaTransport != "RTP/AVP" ) + throw Exception( "Unsupported media transport '"+mediaTransport+"' in SDP media attribute '"+line+"'" ); + int payloadType = atoi(tokens[3].c_str()); + currMedia = new MediaDescriptor( mediaType, mediaPort, mediaNumPorts, mediaTransport, payloadType ); + mMediaList.push_back( currMedia ); + break; + } } + } } SessionDescriptor::~SessionDescriptor() { - if ( mConnInfo ) - delete mConnInfo; - if ( mBandInfo ) - delete mBandInfo; - for ( unsigned int i = 0; i < mMediaList.size(); i++ ) - delete mMediaList[i]; + if ( mConnInfo ) + delete mConnInfo; + if ( mBandInfo ) + delete mBandInfo; + for ( unsigned int i = 0; i < mMediaList.size(); i++ ) + delete mMediaList[i]; } AVFormatContext *SessionDescriptor::generateFormatContext() const { - AVFormatContext *formatContext = avformat_alloc_context(); + AVFormatContext *formatContext = avformat_alloc_context(); - strncpy( formatContext->filename, mUrl.c_str(), sizeof(formatContext->filename) ); + strncpy( formatContext->filename, mUrl.c_str(), sizeof(formatContext->filename) ); /* - if ( mName.length() ) - strncpy( formatContext->title, mName.c_str(), sizeof(formatContext->title) ); - if ( mInfo.length() ) - strncpy( formatContext->comment, mInfo.c_str(), sizeof(formatContext->comment) ); + if ( mName.length() ) + strncpy( formatContext->title, mName.c_str(), sizeof(formatContext->title) ); + if ( mInfo.length() ) + strncpy( formatContext->comment, mInfo.c_str(), sizeof(formatContext->comment) ); */ - //formatContext->nb_streams = mMediaList.size(); - for ( unsigned int i = 0; i < mMediaList.size(); i++ ) - { - const MediaDescriptor *mediaDesc = mMediaList[i]; + //formatContext->nb_streams = mMediaList.size(); + for ( unsigned int i = 0; i < mMediaList.size(); i++ ) + { + const MediaDescriptor *mediaDesc = mMediaList[i]; #if !LIBAVFORMAT_VERSION_CHECK(53, 10, 0, 17, 0) - AVStream *stream = av_new_stream( formatContext, i ); + AVStream *stream = av_new_stream( formatContext, i ); #else - AVStream *stream = avformat_new_stream( formatContext, NULL ); - stream->id = i; + AVStream *stream = avformat_new_stream( formatContext, NULL ); + stream->id = i; #endif - Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); + Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - if ( mediaDesc->getType() == "video" ) - stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; - else if ( mediaDesc->getType() == "audio" ) - stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; - else if ( mediaDesc->getType() == "application" ) - stream->codec->codec_type = AVMEDIA_TYPE_DATA; + if ( mediaDesc->getType() == "video" ) + stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; + else if ( mediaDesc->getType() == "audio" ) + stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; + else if ( mediaDesc->getType() == "application" ) + stream->codec->codec_type = AVMEDIA_TYPE_DATA; #else - if ( mediaDesc->getType() == "video" ) - stream->codec->codec_type = CODEC_TYPE_VIDEO; - else if ( mediaDesc->getType() == "audio" ) - stream->codec->codec_type = CODEC_TYPE_AUDIO; - else if ( mediaDesc->getType() == "application" ) - stream->codec->codec_type = CODEC_TYPE_DATA; + if ( mediaDesc->getType() == "video" ) + stream->codec->codec_type = CODEC_TYPE_VIDEO; + else if ( mediaDesc->getType() == "audio" ) + stream->codec->codec_type = CODEC_TYPE_AUDIO; + else if ( mediaDesc->getType() == "application" ) + stream->codec->codec_type = CODEC_TYPE_DATA; #endif #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) - std::string codec_name; + std::string codec_name; #endif - if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC ) + if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC ) + { + // Look in static table + for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ ) + { + if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() ) { - // Look in static table - for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ ) - { - if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() ) - { - Debug( 1, "Got static payload type %d, %s", smStaticPayloads[i].payloadType, smStaticPayloads[i].payloadName ); + Debug( 1, "Got static payload type %d, %s", smStaticPayloads[i].payloadType, smStaticPayloads[i].payloadName ); #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) - codec_name = std::string( smStaticPayloads[i].payloadName ); + codec_name = std::string( smStaticPayloads[i].payloadName ); #else - strncpy( stream->codec->codec_name, smStaticPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; + strncpy( stream->codec->codec_name, smStaticPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; #endif - stream->codec->codec_type = smStaticPayloads[i].codecType; - stream->codec->codec_id = smStaticPayloads[i].codecId; - stream->codec->sample_rate = smStaticPayloads[i].clockRate; - break; - } - } + stream->codec->codec_type = smStaticPayloads[i].codecType; + stream->codec->codec_id = smStaticPayloads[i].codecId; + stream->codec->sample_rate = smStaticPayloads[i].clockRate; + break; } - else + } + } + else + { + // Look in dynamic table + for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) + { + if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) { - // Look in dynamic table - for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) - { - if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) - { - Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName ); + Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName ); #if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) - codec_name = std::string( smStaticPayloads[i].payloadName ); + codec_name = std::string( smStaticPayloads[i].payloadName ); #else - strncpy( stream->codec->codec_name, smDynamicPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; + strncpy( stream->codec->codec_name, smDynamicPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; #endif - stream->codec->codec_type = smDynamicPayloads[i].codecType; - stream->codec->codec_id = smDynamicPayloads[i].codecId; - stream->codec->sample_rate = mediaDesc->getClock(); - break; - } - } - } - -#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) - if ( codec_name.empty() ) -#else - if ( !stream->codec->codec_name[0] ) -#endif - { - Warning( "Can't find payload details for %s payload type %d, name %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); - //return( 0 ); - } - if ( mediaDesc->getWidth() ) - stream->codec->width = mediaDesc->getWidth(); - if ( mediaDesc->getHeight() ) - stream->codec->height = mediaDesc->getHeight(); - if ( stream->codec->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size()) - { - uint8_t start_sequence[]= { 0, 0, 1 }; - stream->codec->extradata_size= 0; - stream->codec->extradata= NULL; - char pvalue[1024], *value = pvalue; - - strcpy(pvalue, mediaDesc->getSprops().c_str()); - - while (*value) { - char base64packet[1024]; - uint8_t decoded_packet[1024]; - uint32_t packet_size; - char *dst = base64packet; - - while (*value && *value != ',' - && (dst - base64packet) < (long)(sizeof(base64packet)) - 1) { - *dst++ = *value++; - } - *dst++ = '\0'; - - if (*value == ',') - value++; - - packet_size= av_base64_decode(decoded_packet, (const char *)base64packet, (int)sizeof(decoded_packet)); - Hexdump(4, (char *)decoded_packet, packet_size); - if (packet_size) { - uint8_t *dest = - (uint8_t *)av_malloc(packet_size + sizeof(start_sequence) + - stream->codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if(dest) { - if(stream->codec->extradata_size) { - // av_realloc? - memcpy(dest, stream->codec->extradata, stream->codec->extradata_size); - av_free(stream->codec->extradata); - } - - memcpy(dest+stream->codec->extradata_size, start_sequence, sizeof(start_sequence)); - memcpy(dest+stream->codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size); - memset(dest+stream->codec->extradata_size+sizeof(start_sequence)+ - packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - - stream->codec->extradata= dest; - stream->codec->extradata_size+= sizeof(start_sequence)+packet_size; -// } else { -// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!"); -// return AVERROR(ENOMEM); - } - } - } + stream->codec->codec_type = smDynamicPayloads[i].codecType; + stream->codec->codec_id = smDynamicPayloads[i].codecId; + stream->codec->sample_rate = mediaDesc->getClock(); + break; } + } } - return( formatContext ); +#if LIBAVCODEC_VERSION_CHECK(55, 50, 3, 60, 103) + if ( codec_name.empty() ) +#else + if ( !stream->codec->codec_name[0] ) +#endif + { + Warning( "Can't find payload details for %s payload type %d, name %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); + //return( 0 ); + } + if ( mediaDesc->getWidth() ) + stream->codec->width = mediaDesc->getWidth(); + if ( mediaDesc->getHeight() ) + stream->codec->height = mediaDesc->getHeight(); + if ( stream->codec->codec_id == AV_CODEC_ID_H264 && mediaDesc->getSprops().size()) + { + uint8_t start_sequence[]= { 0, 0, 1 }; + stream->codec->extradata_size= 0; + stream->codec->extradata= NULL; + char pvalue[1024], *value = pvalue; + + strcpy(pvalue, mediaDesc->getSprops().c_str()); + + while (*value) { + char base64packet[1024]; + uint8_t decoded_packet[1024]; + uint32_t packet_size; + char *dst = base64packet; + + while (*value && *value != ',' + && (dst - base64packet) < (long)(sizeof(base64packet)) - 1) { + *dst++ = *value++; + } + *dst++ = '\0'; + + if (*value == ',') + value++; + + packet_size= av_base64_decode(decoded_packet, (const char *)base64packet, (int)sizeof(decoded_packet)); + Hexdump(4, (char *)decoded_packet, packet_size); + if (packet_size) { + uint8_t *dest = + (uint8_t *)av_malloc(packet_size + sizeof(start_sequence) + + stream->codec->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if(dest) { + if(stream->codec->extradata_size) { + // av_realloc? + memcpy(dest, stream->codec->extradata, stream->codec->extradata_size); + av_free(stream->codec->extradata); + } + + memcpy(dest+stream->codec->extradata_size, start_sequence, sizeof(start_sequence)); + memcpy(dest+stream->codec->extradata_size+sizeof(start_sequence), decoded_packet, packet_size); + memset(dest+stream->codec->extradata_size+sizeof(start_sequence)+ + packet_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + + stream->codec->extradata= dest; + stream->codec->extradata_size+= sizeof(start_sequence)+packet_size; +// } else { +// av_log(codec, AV_LOG_ERROR, "Unable to allocate memory for extradata!"); +// return AVERROR(ENOMEM); + } + } + } + } + } + + return( formatContext ); } #endif // HAVE_LIBAVFORMAT diff --git a/src/zm_sdp.h b/src/zm_sdp.h index 21eb227c1..2d08905c8 100644 --- a/src/zm_sdp.h +++ b/src/zm_sdp.h @@ -34,204 +34,204 @@ class SessionDescriptor { protected: - enum { PAYLOAD_TYPE_DYNAMIC=96 }; + enum { PAYLOAD_TYPE_DYNAMIC=96 }; - struct StaticPayloadDesc - { - int payloadType; - const char payloadName[6]; + struct StaticPayloadDesc + { + int payloadType; + const char payloadName[6]; #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - AVMediaType codecType; + AVMediaType codecType; #else - enum CodecType codecType; + enum CodecType codecType; #endif - _AVCODECID codecId; - int clockRate; - int autoChannels; - }; + _AVCODECID codecId; + int clockRate; + int autoChannels; + }; - struct DynamicPayloadDesc - { - const char payloadName[32]; + struct DynamicPayloadDesc + { + const char payloadName[32]; #if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0)) - AVMediaType codecType; + AVMediaType codecType; #else - enum CodecType codecType; + enum CodecType codecType; #endif - _AVCODECID codecId; + _AVCODECID codecId; - //int clockRate; - //int autoChannels; - }; + //int clockRate; + //int autoChannels; + }; public: - class ConnInfo - { - protected: - std::string mNetworkType; - std::string mAddressType; - std::string mAddress; - int mTtl; - int mNoAddresses; + class ConnInfo + { + protected: + std::string mNetworkType; + std::string mAddressType; + std::string mAddress; + int mTtl; + int mNoAddresses; - public: - ConnInfo( const std::string &connInfo ); - }; + public: + ConnInfo( const std::string &connInfo ); + }; - class BandInfo - { - protected: - std::string mType; - int mValue; + class BandInfo + { + protected: + std::string mType; + int mValue; - public: - BandInfo( const std::string &bandInfo ); - }; + public: + BandInfo( const std::string &bandInfo ); + }; - class MediaDescriptor - { - protected: - std::string mType; - int mPort; - int mNumPorts; - std::string mTransport; - int mPayloadType; + class MediaDescriptor + { + protected: + std::string mType; + int mPort; + int mNumPorts; + std::string mTransport; + int mPayloadType; - std::string mPayloadDesc; - std::string mControlUrl; - double mFrameRate; - int mClock; - int mWidth; - int mHeight; - std::string mSprops; - - ConnInfo *mConnInfo; - - public: - MediaDescriptor( const std::string &type, int port, int numPorts, const std::string &transport, int payloadType ); - - const std::string &getType() const - { - return( mType ); - } - int getPort() const - { - return( mPort ); - } - int getNumPorts() const - { - return( mNumPorts ); - } - const std::string &getTransport() const - { - return( mTransport ); - } - const int getPayloadType() const - { - return( mPayloadType ); - } - - const std::string &getPayloadDesc() const - { - return( mPayloadDesc ); - } - void setPayloadDesc( const std::string &payloadDesc ) - { - mPayloadDesc = payloadDesc; - } - - const std::string &getControlUrl() const - { - return( mControlUrl ); - } - void setControlUrl( const std::string &controlUrl ) - { - mControlUrl = controlUrl; - } - - const int getClock() const - { - return( mClock ); - } - void setClock( int clock ) - { - mClock = clock; - } - - void setFrameSize( int width, int height ) - { - mWidth = width; - mHeight = height; - } - int getWidth() const - { - return( mWidth ); - } - int getHeight() const - { - return( mHeight ); - } - - void setSprops(const std::string props) - { - mSprops = props; - } - const std::string getSprops() const - { - return ( mSprops ); - } - const double getFrameRate() const - { - return( mFrameRate ); - } - void setFrameRate( double frameRate ) - { - mFrameRate = frameRate; - } - }; - - typedef std::vector MediaList; - -protected: - static StaticPayloadDesc smStaticPayloads[]; - static DynamicPayloadDesc smDynamicPayloads[]; - -protected: - std::string mUrl; - - std::string mVersion; - std::string mOwner; - std::string mName; - std::string mInfo; + std::string mPayloadDesc; + std::string mControlUrl; + double mFrameRate; + int mClock; + int mWidth; + int mHeight; + std::string mSprops; ConnInfo *mConnInfo; - BandInfo *mBandInfo; - std::string mTimeInfo; - StringVector mAttributes; - MediaList mMediaList; + public: + MediaDescriptor( const std::string &type, int port, int numPorts, const std::string &transport, int payloadType ); + + const std::string &getType() const + { + return( mType ); + } + int getPort() const + { + return( mPort ); + } + int getNumPorts() const + { + return( mNumPorts ); + } + const std::string &getTransport() const + { + return( mTransport ); + } + const int getPayloadType() const + { + return( mPayloadType ); + } + + const std::string &getPayloadDesc() const + { + return( mPayloadDesc ); + } + void setPayloadDesc( const std::string &payloadDesc ) + { + mPayloadDesc = payloadDesc; + } + + const std::string &getControlUrl() const + { + return( mControlUrl ); + } + void setControlUrl( const std::string &controlUrl ) + { + mControlUrl = controlUrl; + } + + const int getClock() const + { + return( mClock ); + } + void setClock( int clock ) + { + mClock = clock; + } + + void setFrameSize( int width, int height ) + { + mWidth = width; + mHeight = height; + } + int getWidth() const + { + return( mWidth ); + } + int getHeight() const + { + return( mHeight ); + } + + void setSprops(const std::string props) + { + mSprops = props; + } + const std::string getSprops() const + { + return ( mSprops ); + } + const double getFrameRate() const + { + return( mFrameRate ); + } + void setFrameRate( double frameRate ) + { + mFrameRate = frameRate; + } + }; + + typedef std::vector MediaList; + +protected: + static StaticPayloadDesc smStaticPayloads[]; + static DynamicPayloadDesc smDynamicPayloads[]; + +protected: + std::string mUrl; + + std::string mVersion; + std::string mOwner; + std::string mName; + std::string mInfo; + + ConnInfo *mConnInfo; + BandInfo *mBandInfo; + std::string mTimeInfo; + StringVector mAttributes; + + MediaList mMediaList; public: - SessionDescriptor( const std::string &url, const std::string &sdp ); - ~SessionDescriptor(); + SessionDescriptor( const std::string &url, const std::string &sdp ); + ~SessionDescriptor(); - const std::string &getUrl() const - { - return( mUrl ); - } + const std::string &getUrl() const + { + return( mUrl ); + } - int getNumStreams() const - { - return( mMediaList.size() ); - } - MediaDescriptor *getStream( int index ) - { - if ( index < 0 || (unsigned int)index >= mMediaList.size() ) - return( 0 ); - return( mMediaList[index] ); - } + int getNumStreams() const + { + return( mMediaList.size() ); + } + MediaDescriptor *getStream( int index ) + { + if ( index < 0 || (unsigned int)index >= mMediaList.size() ) + return( 0 ); + return( mMediaList[index] ); + } - AVFormatContext *generateFormatContext() const; + AVFormatContext *generateFormatContext() const; }; #if 0 v=0 @@ -254,7 +254,7 @@ a=mpeg4-esid:201 m=audio 0 RTP/AVP 0 b=AS:64 a=control:trackID=2 - + #endif #endif // ZM_SDP_H diff --git a/src/zm_sendfile.h b/src/zm_sendfile.h index ce3405d66..0e35388ea 100644 --- a/src/zm_sendfile.h +++ b/src/zm_sendfile.h @@ -1,30 +1,30 @@ #ifdef HAVE_SENDFILE4_SUPPORT #include int zm_sendfile(int out_fd, int in_fd, off_t *offset, size_t size) { - int err; + int err; - err = sendfile(out_fd, in_fd, offset, size); - if (err < 0) - return -errno; + err = sendfile(out_fd, in_fd, offset, size); + if (err < 0) + return -errno; - return err; + return err; } #elif HAVE_SENDFILE7_SUPPORT #include #include #include int zm_sendfile(int out_fd, int in_fd, off_t *offset, off_t size) { - int err; - err = sendfile(in_fd, out_fd, *offset, size, NULL, &size, 0); - if (err && errno != EAGAIN) - return -errno; + int err; + err = sendfile(in_fd, out_fd, *offset, size, NULL, &size, 0); + if (err && errno != EAGAIN) + return -errno; - if (size) { - *offset += size; - return size; - } + if (size) { + *offset += size; + return size; + } - return -EAGAIN; + return -EAGAIN; } #else #error "Your platform does not support sendfile. Sorry." diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index 77c94e68c..3bab38f86 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -32,326 +32,326 @@ StreamBase::~StreamBase() { #if HAVE_LIBAVCODEC - if ( vid_stream ) - { - delete vid_stream; - vid_stream = NULL; - } + if ( vid_stream ) + { + delete vid_stream; + vid_stream = NULL; + } #endif - closeComms(); + closeComms(); } bool StreamBase::loadMonitor( int monitor_id ) { - if ( !(monitor = Monitor::Load( monitor_id, false, Monitor::QUERY )) ) - { - Fatal( "Unable to load monitor id %d for streaming", monitor_id ); - return( false ); - } - monitor->connect(); - return( true ); + if ( !(monitor = Monitor::Load( monitor_id, false, Monitor::QUERY )) ) + { + Fatal( "Unable to load monitor id %d for streaming", monitor_id ); + return( false ); + } + monitor->connect(); + return( true ); } bool StreamBase::checkInitialised() { - if ( !monitor ) - { - Fatal( "Cannot stream, not initialised" ); - return( false ); - } - return( true ); + if ( !monitor ) + { + Fatal( "Cannot stream, not initialised" ); + return( false ); + } + return( true ); } void StreamBase::updateFrameRate( double fps ) { - base_fps = fps; - effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; - frame_mod = 1; - Debug( 3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod ); - // Min frame repeat? - while( effective_fps > maxfps ) - { - effective_fps /= 2.0; - frame_mod *= 2; - } - Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod ); + base_fps = fps; + effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; + frame_mod = 1; + Debug( 3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod ); + // Min frame repeat? + while( effective_fps > maxfps ) + { + effective_fps /= 2.0; + frame_mod *= 2; + } + Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod ); } bool StreamBase::checkCommandQueue() { - if ( sd >= 0 ) + if ( sd >= 0 ) + { + CmdMsg msg; + memset( &msg, 0, sizeof(msg) ); + int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 ); + if ( nbytes < 0 ) { - CmdMsg msg; - memset( &msg, 0, sizeof(msg) ); - int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 ); - if ( nbytes < 0 ) - { - if ( errno != EAGAIN ) - { - Fatal( "recvfrom(), errno = %d, error = %s", errno, strerror(errno) ); - } - } - //else if ( (nbytes != sizeof(msg)) ) - //{ - //Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes ); - //} - else - { - processCommand( &msg ); - return( true ); - } + if ( errno != EAGAIN ) + { + Fatal( "recvfrom(), errno = %d, error = %s", errno, strerror(errno) ); + } } - return( false ); + //else if ( (nbytes != sizeof(msg)) ) + //{ + //Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes ); + //} + else + { + processCommand( &msg ); + return( true ); + } + } + return( false ); } Image *StreamBase::prepareImage( Image *image ) { - static int last_scale = 0; - static int last_zoom = 0; - static int last_x = 0; - static int last_y = 0; + static int last_scale = 0; + static int last_zoom = 0; + static int last_x = 0; + static int last_y = 0; - if ( !last_scale ) - last_scale = scale; - if ( !last_zoom ) - last_zoom = zoom; - - // Do not bother to scale zoomed in images, just crop them and let the browser scale - // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. - bool optimisedScaling = false; - - bool image_copied = false; - - int mag = (scale * zoom) / ZM_SCALE_BASE; - int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; - Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag ); - - int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; - int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; - Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag ); - - int base_image_width = image->Width(), base_image_height = image->Height(); - Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height ); - - int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; - Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height ); - - int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; - Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height ); - - int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; - Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height ); - - int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; - Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height ); - - int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; - Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height ); - - int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; - Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height ); - - int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; - Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height ); - - int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag; - Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height ); - - if ( mag != ZM_SCALE_BASE ) - { - if ( act_mag != ZM_SCALE_BASE ) - { - Debug( 3, "Magnifying by %d", mag ); - if ( !image_copied ) - { - static Image copy_image; - copy_image.Assign( *image ); - image = ©_image; - image_copied = true; - } - image->Scale( mag ); - } - } - - Debug( 3, "Real image width = %d, height = %d", image->Width(), image->Height() ); - - if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height ) - { - static Box last_crop; - - if ( mag != last_mag || x != last_x || y != last_y ) - { - Debug( 3, "Got click at %d,%d x %d", x, y, mag ); - - //if ( !last_mag ) - //last_mag = mag; - - if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) ) - last_crop = Box(); - - Debug( 3, "Recalculating crop" ); - // Recalculate crop parameters, as %ges - int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image - click_x += ( x * 100 ) / last_virt_image_width; - int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image - click_y += ( y * 100 ) / last_virt_image_height; - Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y ); - - // Convert the click locations to the current image pixels - click_x = ( click_x * act_image_width ) / 100; - click_y = ( click_y * act_image_height ) / 100; - Debug( 3, "Got readjusted click at %d,%d", click_x, click_y ); - - int lo_x = click_x - (send_image_width/2); - if ( lo_x < 0 ) - lo_x = 0; - int hi_x = lo_x + (send_image_width-1); - if ( hi_x >= act_image_width ) - { - hi_x = act_image_width - 1; - lo_x = hi_x - (send_image_width - 1); - } - - int lo_y = click_y - (send_image_height/2); - if ( lo_y < 0 ) - lo_y = 0; - int hi_y = lo_y + (send_image_height-1); - if ( hi_y >= act_image_height ) - { - hi_y = act_image_height - 1; - lo_y = hi_y - (send_image_height - 1); - } - last_crop = Box( lo_x, lo_y, hi_x, hi_y ); - } - Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() ); - if ( !image_copied ) - { - static Image copy_image; - copy_image.Assign( *image ); - image = ©_image; - image_copied = true; - } - image->Crop( last_crop ); - } + if ( !last_scale ) last_scale = scale; + if ( !last_zoom ) last_zoom = zoom; - last_x = x; - last_y = y; - return( image ); + // Do not bother to scale zoomed in images, just crop them and let the browser scale + // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. + bool optimisedScaling = false; + + bool image_copied = false; + + int mag = (scale * zoom) / ZM_SCALE_BASE; + int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; + Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag ); + + int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; + int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; + Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag ); + + int base_image_width = image->Width(), base_image_height = image->Height(); + Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height ); + + int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; + Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height ); + + int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; + Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height ); + + int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; + Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height ); + + int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; + Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height ); + + int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; + Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height ); + + int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; + Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height ); + + int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; + Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height ); + + int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag; + Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height ); + + if ( mag != ZM_SCALE_BASE ) + { + if ( act_mag != ZM_SCALE_BASE ) + { + Debug( 3, "Magnifying by %d", mag ); + if ( !image_copied ) + { + static Image copy_image; + copy_image.Assign( *image ); + image = ©_image; + image_copied = true; + } + image->Scale( mag ); + } + } + + Debug( 3, "Real image width = %d, height = %d", image->Width(), image->Height() ); + + if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height ) + { + static Box last_crop; + + if ( mag != last_mag || x != last_x || y != last_y ) + { + Debug( 3, "Got click at %d,%d x %d", x, y, mag ); + + //if ( !last_mag ) + //last_mag = mag; + + if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) ) + last_crop = Box(); + + Debug( 3, "Recalculating crop" ); + // Recalculate crop parameters, as %ges + int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image + click_x += ( x * 100 ) / last_virt_image_width; + int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image + click_y += ( y * 100 ) / last_virt_image_height; + Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y ); + + // Convert the click locations to the current image pixels + click_x = ( click_x * act_image_width ) / 100; + click_y = ( click_y * act_image_height ) / 100; + Debug( 3, "Got readjusted click at %d,%d", click_x, click_y ); + + int lo_x = click_x - (send_image_width/2); + if ( lo_x < 0 ) + lo_x = 0; + int hi_x = lo_x + (send_image_width-1); + if ( hi_x >= act_image_width ) + { + hi_x = act_image_width - 1; + lo_x = hi_x - (send_image_width - 1); + } + + int lo_y = click_y - (send_image_height/2); + if ( lo_y < 0 ) + lo_y = 0; + int hi_y = lo_y + (send_image_height-1); + if ( hi_y >= act_image_height ) + { + hi_y = act_image_height - 1; + lo_y = hi_y - (send_image_height - 1); + } + last_crop = Box( lo_x, lo_y, hi_x, hi_y ); + } + Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() ); + if ( !image_copied ) + { + static Image copy_image; + copy_image.Assign( *image ); + image = ©_image; + image_copied = true; + } + image->Crop( last_crop ); + } + last_scale = scale; + last_zoom = zoom; + last_x = x; + last_y = y; + + return( image ); } bool StreamBase::sendTextFrame( const char *frame_text ) { - Debug( 2, "Sending text frame '%s'", frame_text ); + Debug( 2, "Sending text frame '%s'", frame_text ); - Image image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder() ); - image.Annotate( frame_text, image.centreCoord( frame_text ) ); + Image image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder() ); + image.Annotate( frame_text, image.centreCoord( frame_text ) ); - if ( scale != 100 ) - { - image.Scale( scale ); - } + if ( scale != 100 ) + { + image.Scale( scale ); + } #if HAVE_LIBAVCODEC - if ( type == STREAM_MPEG ) + if ( type == STREAM_MPEG ) + { + if ( !vid_stream ) { - if ( !vid_stream ) - { - vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.SubpixelOrder(), image.Width(), image.Height() ); - fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); - vid_stream->OpenStream(); - } - /* double pts = */ vid_stream->EncodeFrame( image.Buffer(), image.Size() ); + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.SubpixelOrder(), image.Width(), image.Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); } - else + /* double pts = */ vid_stream->EncodeFrame( image.Buffer(), image.Size() ); + } + else #endif // HAVE_LIBAVCODEC + { + static unsigned char buffer[ZM_MAX_IMAGE_SIZE]; + int n_bytes = 0; + + image.EncodeJpeg( buffer, &n_bytes ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + fprintf( stdout, "Content-Length: %d\r\n", n_bytes ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + if ( fwrite( buffer, n_bytes, 1, stdout ) != 1 ) { - static unsigned char buffer[ZM_MAX_IMAGE_SIZE]; - int n_bytes = 0; - - image.EncodeJpeg( buffer, &n_bytes ); - - fprintf( stdout, "--ZoneMinderFrame\r\n" ); - fprintf( stdout, "Content-Length: %d\r\n", n_bytes ); - fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); - if ( fwrite( buffer, n_bytes, 1, stdout ) != 1 ) - { - Error( "Unable to send stream text frame: %s", strerror(errno) ); - return( false ); - } - fprintf( stdout, "\r\n\r\n" ); - fflush( stdout ); + Error( "Unable to send stream text frame: %s", strerror(errno) ); + return( false ); } - last_frame_sent = TV_2_FLOAT( now ); - return( true ); + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); } void StreamBase::openComms() { - if ( connkey > 0 ) + if ( connkey > 0 ) + { + + snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey); + + lock_fd = open(sock_path_lock, O_CREAT|O_WRONLY, S_IRUSR | S_IWUSR); + if ( lock_fd <= 0 ) { - - snprintf( sock_path_lock, sizeof(sock_path_lock), "%s/zms-%06d.lock", config.path_socks, connkey); - - lock_fd = open(sock_path_lock, O_CREAT|O_WRONLY, S_IRUSR | S_IWUSR); - if ( lock_fd <= 0 ) - { - Error("Unable to open sock lock file %s: %s", sock_path_lock, strerror(errno) ); - lock_fd = 0; - } - else if ( flock(lock_fd, LOCK_EX) != 0 ) - { - Error("Unable to lock sock lock file %s: %s", sock_path_lock, strerror(errno) ); - - close(lock_fd); - lock_fd = 0; - } - else - { - Debug( 1, "We have obtained a lock on %s fd: %d", sock_path_lock, lock_fd); - } - - - sd = socket( AF_UNIX, SOCK_DGRAM, 0 ); - if ( sd < 0 ) - { - Fatal( "Can't create socket: %s", strerror(errno) ); - } - - snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); - unlink( loc_sock_path ); - - strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) ); - loc_addr.sun_family = AF_UNIX; - if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 ) - { - Fatal( "Can't bind: %s", strerror(errno) ); - } - - snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey ); - strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) ); - rem_addr.sun_family = AF_UNIX; + Error("Unable to open sock lock file %s: %s", sock_path_lock, strerror(errno) ); + lock_fd = 0; } + else if ( flock(lock_fd, LOCK_EX) != 0 ) + { + Error("Unable to lock sock lock file %s: %s", sock_path_lock, strerror(errno) ); + + close(lock_fd); + lock_fd = 0; + } + else + { + Debug( 1, "We have obtained a lock on %s fd: %d", sock_path_lock, lock_fd); + } + + + sd = socket( AF_UNIX, SOCK_DGRAM, 0 ); + if ( sd < 0 ) + { + Fatal( "Can't create socket: %s", strerror(errno) ); + } + + snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); + unlink( loc_sock_path ); + + strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) ); + loc_addr.sun_family = AF_UNIX; + if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 ) + { + Fatal( "Can't bind: %s", strerror(errno) ); + } + + snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey ); + strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) ); + rem_addr.sun_family = AF_UNIX; + } } void StreamBase::closeComms() { - if ( connkey > 0 ) + if ( connkey > 0 ) + { + if ( sd >= 0 ) { - if ( sd >= 0 ) - { - close( sd ); - sd = -1; - } - if ( loc_sock_path[0] ) - { - unlink( loc_sock_path ); - } - if (lock_fd > 0) - { - close(lock_fd); //close it rather than unlock it incase it got deleted. - unlink(sock_path_lock); - } + close( sd ); + sd = -1; } + if ( loc_sock_path[0] ) + { + unlink( loc_sock_path ); + } + if (lock_fd > 0) + { + close(lock_fd); //close it rather than unlock it incase it got deleted. + unlink(sock_path_lock); + } + } } diff --git a/src/zm_stream.h b/src/zm_stream.h index 4f6442725..c7df53d16 100644 --- a/src/zm_stream.h +++ b/src/zm_stream.h @@ -33,149 +33,149 @@ class Monitor; class StreamBase { public: - typedef enum { STREAM_JPEG, STREAM_RAW, STREAM_ZIP, STREAM_SINGLE, STREAM_MPEG } StreamType; + typedef enum { STREAM_JPEG, STREAM_RAW, STREAM_ZIP, STREAM_SINGLE, STREAM_MPEG } StreamType; protected: - static const int MAX_STREAM_DELAY = 5; // Seconds + static const int MAX_STREAM_DELAY = 5; // Seconds - static const StreamType DEFAULT_TYPE = STREAM_JPEG; - enum { DEFAULT_RATE=ZM_RATE_BASE }; - enum { DEFAULT_SCALE=ZM_SCALE_BASE }; - enum { DEFAULT_ZOOM=ZM_SCALE_BASE }; - enum { DEFAULT_MAXFPS=10 }; - enum { DEFAULT_BITRATE=100000 }; + static const StreamType DEFAULT_TYPE = STREAM_JPEG; + enum { DEFAULT_RATE=ZM_RATE_BASE }; + enum { DEFAULT_SCALE=ZM_SCALE_BASE }; + enum { DEFAULT_ZOOM=ZM_SCALE_BASE }; + enum { DEFAULT_MAXFPS=10 }; + enum { DEFAULT_BITRATE=100000 }; protected: - typedef struct { - int msg_type; - char msg_data[16]; - } CmdMsg; + typedef struct { + int msg_type; + char msg_data[16]; + } CmdMsg; - typedef struct { - int msg_type; - char msg_data[256]; - } DataMsg; + typedef struct { + int msg_type; + char msg_data[256]; + } DataMsg; - typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType; - typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUIT, CMD_QUERY=99 } MsgCommand; + typedef enum { MSG_CMD=1, MSG_DATA_WATCH, MSG_DATA_EVENT } MsgType; + typedef enum { CMD_NONE=0, CMD_PAUSE, CMD_PLAY, CMD_STOP, CMD_FASTFWD, CMD_SLOWFWD, CMD_SLOWREV, CMD_FASTREV, CMD_ZOOMIN, CMD_ZOOMOUT, CMD_PAN, CMD_SCALE, CMD_PREV, CMD_NEXT, CMD_SEEK, CMD_VARPLAY, CMD_GET_IMAGE, CMD_QUIT, CMD_QUERY=99 } MsgCommand; protected: - Monitor *monitor; + Monitor *monitor; - StreamType type; - const char *format; - int replay_rate; - int scale; - int zoom; - double maxfps; - int bitrate; - unsigned short x, y; + StreamType type; + const char *format; + int replay_rate; + int scale; + int zoom; + double maxfps; + int bitrate; + unsigned short x, y; protected: - int connkey; - int sd; - char loc_sock_path[PATH_MAX]; - struct sockaddr_un loc_addr; - char rem_sock_path[PATH_MAX]; - struct sockaddr_un rem_addr; - char sock_path_lock[PATH_MAX]; - int lock_fd; + int connkey; + int sd; + char loc_sock_path[PATH_MAX]; + struct sockaddr_un loc_addr; + char rem_sock_path[PATH_MAX]; + struct sockaddr_un rem_addr; + char sock_path_lock[PATH_MAX]; + int lock_fd; protected: - bool paused; - int step; + bool paused; + int step; - struct timeval now; + struct timeval now; - double base_fps; - double effective_fps; - int frame_mod; + double base_fps; + double effective_fps; + int frame_mod; - double last_frame_sent; - struct timeval last_frame_timestamp; + double last_frame_sent; + struct timeval last_frame_timestamp; -#if HAVE_LIBAVCODEC - VideoStream *vid_stream; -#endif // HAVE_LIBAVCODEC +#if HAVE_LIBAVCODEC + VideoStream *vid_stream; +#endif // HAVE_LIBAVCODEC - CmdMsg msg; + CmdMsg msg; protected: - bool loadMonitor( int monitor_id ); - bool checkInitialised(); - void updateFrameRate( double fps ); - Image *prepareImage( Image *image ); - bool sendTextFrame( const char *text ); - bool checkCommandQueue(); - virtual void processCommand( const CmdMsg *msg )=0; + bool loadMonitor( int monitor_id ); + bool checkInitialised(); + void updateFrameRate( double fps ); + Image *prepareImage( Image *image ); + bool sendTextFrame( const char *text ); + bool checkCommandQueue(); + virtual void processCommand( const CmdMsg *msg )=0; public: - StreamBase() - { - monitor = 0; + StreamBase() + { + monitor = 0; - type = DEFAULT_TYPE; - format = ""; - replay_rate = DEFAULT_RATE; - scale = DEFAULT_SCALE; - zoom = DEFAULT_ZOOM; - maxfps = DEFAULT_MAXFPS; - bitrate = DEFAULT_BITRATE; + type = DEFAULT_TYPE; + format = ""; + replay_rate = DEFAULT_RATE; + scale = DEFAULT_SCALE; + zoom = DEFAULT_ZOOM; + maxfps = DEFAULT_MAXFPS; + bitrate = DEFAULT_BITRATE; - paused = false; - step = 0; - x = 0; - y = 0; + paused = false; + step = 0; + x = 0; + y = 0; - connkey = 0; - sd = -1; - lock_fd = 0; - memset( &loc_sock_path, 0, sizeof(loc_sock_path) ); - memset( &loc_addr, 0, sizeof(loc_addr) ); - memset( &rem_sock_path, 0, sizeof(rem_sock_path) ); - memset( &rem_addr, 0, sizeof(rem_addr) ); + connkey = 0; + sd = -1; + lock_fd = 0; + memset( &loc_sock_path, 0, sizeof(loc_sock_path) ); + memset( &loc_addr, 0, sizeof(loc_addr) ); + memset( &rem_sock_path, 0, sizeof(rem_sock_path) ); + memset( &rem_addr, 0, sizeof(rem_addr) ); - base_fps = 0.0; - effective_fps = 0.0; - frame_mod = 1; + base_fps = 0.0; + effective_fps = 0.0; + frame_mod = 1; -#if HAVE_LIBAVCODEC - vid_stream = 0; -#endif // HAVE_LIBAVCODEC - } - virtual ~StreamBase(); +#if HAVE_LIBAVCODEC + vid_stream = 0; +#endif // HAVE_LIBAVCODEC + } + virtual ~StreamBase(); - void setStreamType( StreamType p_type ) - { - type = p_type; - } - void setStreamFormat( const char *p_format ) - { - format = p_format; - } - void setStreamScale( int p_scale ) - { - scale = p_scale; - } - void setStreamReplayRate( int p_rate ) - { - replay_rate = p_rate; - } - void setStreamMaxFPS( double p_maxfps ) - { - maxfps = p_maxfps; - } - void setStreamBitrate( int p_bitrate ) - { - bitrate = p_bitrate; - } - void setStreamQueue( int p_connkey ) - { - connkey = p_connkey; - } - virtual void openComms(); - virtual void closeComms(); - virtual void runStream()=0; + void setStreamType( StreamType p_type ) + { + type = p_type; + } + void setStreamFormat( const char *p_format ) + { + format = p_format; + } + void setStreamScale( int p_scale ) + { + scale = p_scale; + } + void setStreamReplayRate( int p_rate ) + { + replay_rate = p_rate; + } + void setStreamMaxFPS( double p_maxfps ) + { + maxfps = p_maxfps; + } + void setStreamBitrate( int p_bitrate ) + { + bitrate = p_bitrate; + } + void setStreamQueue( int p_connkey ) + { + connkey = p_connkey; + } + virtual void openComms(); + virtual void closeComms(); + virtual void runStream()=0; }; #endif // ZM_STREAM_H diff --git a/src/zm_thread.cpp b/src/zm_thread.cpp index 09cf0da3f..39b26343a 100644 --- a/src/zm_thread.cpp +++ b/src/zm_thread.cpp @@ -29,311 +29,311 @@ struct timespec getTimeout( int secs ) { - struct timespec timeout; - struct timeval temp_timeout; - gettimeofday( &temp_timeout, 0 ); - timeout.tv_sec = temp_timeout.tv_sec + secs; - timeout.tv_nsec = temp_timeout.tv_usec*1000; - return( timeout ); + struct timespec timeout; + struct timeval temp_timeout; + gettimeofday( &temp_timeout, 0 ); + timeout.tv_sec = temp_timeout.tv_sec + secs; + timeout.tv_nsec = temp_timeout.tv_usec*1000; + return( timeout ); } struct timespec getTimeout( double secs ) { - struct timespec timeout; - struct timeval temp_timeout; - gettimeofday( &temp_timeout, 0 ); - timeout.tv_sec = temp_timeout.tv_sec + int(secs); - timeout.tv_nsec = temp_timeout.tv_usec += (long int)(1000000000.0*(secs-int(secs))); - if ( timeout.tv_nsec > 1000000000 ) - { - timeout.tv_sec += 1; - timeout.tv_nsec -= 1000000000; - } - return( timeout ); + struct timespec timeout; + struct timeval temp_timeout; + gettimeofday( &temp_timeout, 0 ); + timeout.tv_sec = temp_timeout.tv_sec + int(secs); + timeout.tv_nsec = temp_timeout.tv_usec += (long int)(1000000000.0*(secs-int(secs))); + if ( timeout.tv_nsec > 1000000000 ) + { + timeout.tv_sec += 1; + timeout.tv_nsec -= 1000000000; + } + return( timeout ); } Mutex::Mutex() { - if ( pthread_mutex_init( &mMutex, NULL ) < 0 ) - throw ThreadException( stringtf( "Unable to create pthread mutex: %s", strerror(errno) ) ); + if ( pthread_mutex_init( &mMutex, NULL ) < 0 ) + throw ThreadException( stringtf( "Unable to create pthread mutex: %s", strerror(errno) ) ); } Mutex::~Mutex() { - if ( locked() ) - Warning( "Destroying mutex when locked" ); - if ( pthread_mutex_destroy( &mMutex ) < 0 ) - throw ThreadException( stringtf( "Unable to destroy pthread mutex: %s", strerror(errno) ) ); + if ( locked() ) + Warning( "Destroying mutex when locked" ); + if ( pthread_mutex_destroy( &mMutex ) < 0 ) + throw ThreadException( stringtf( "Unable to destroy pthread mutex: %s", strerror(errno) ) ); } void Mutex::lock() { - if ( pthread_mutex_lock( &mMutex ) < 0 ) - throw ThreadException( stringtf( "Unable to lock pthread mutex: %s", strerror(errno) ) ); + if ( pthread_mutex_lock( &mMutex ) < 0 ) + throw ThreadException( stringtf( "Unable to lock pthread mutex: %s", strerror(errno) ) ); } void Mutex::lock( int secs ) { - struct timespec timeout = getTimeout( secs ); - if ( pthread_mutex_timedlock( &mMutex, &timeout ) < 0 ) - throw ThreadException( stringtf( "Unable to timedlock pthread mutex: %s", strerror(errno) ) ); + struct timespec timeout = getTimeout( secs ); + if ( pthread_mutex_timedlock( &mMutex, &timeout ) < 0 ) + throw ThreadException( stringtf( "Unable to timedlock pthread mutex: %s", strerror(errno) ) ); } void Mutex::lock( double secs ) { - struct timespec timeout = getTimeout( secs ); - if ( pthread_mutex_timedlock( &mMutex, &timeout ) < 0 ) - throw ThreadException( stringtf( "Unable to timedlock pthread mutex: %s", strerror(errno) ) ); + struct timespec timeout = getTimeout( secs ); + if ( pthread_mutex_timedlock( &mMutex, &timeout ) < 0 ) + throw ThreadException( stringtf( "Unable to timedlock pthread mutex: %s", strerror(errno) ) ); } void Mutex::unlock() { - if ( pthread_mutex_unlock( &mMutex ) < 0 ) - throw ThreadException( stringtf( "Unable to unlock pthread mutex: %s", strerror(errno) ) ); + if ( pthread_mutex_unlock( &mMutex ) < 0 ) + throw ThreadException( stringtf( "Unable to unlock pthread mutex: %s", strerror(errno) ) ); } bool Mutex::locked() { - int state = pthread_mutex_trylock( &mMutex ); - if ( state != 0 && state != EBUSY ) - throw ThreadException( stringtf( "Unable to trylock pthread mutex: %s", strerror(errno) ) ); - if ( state != EBUSY ) - unlock(); - return( state == EBUSY ); + int state = pthread_mutex_trylock( &mMutex ); + if ( state != 0 && state != EBUSY ) + throw ThreadException( stringtf( "Unable to trylock pthread mutex: %s", strerror(errno) ) ); + if ( state != EBUSY ) + unlock(); + return( state == EBUSY ); } Condition::Condition( Mutex &mutex ) : mMutex( mutex ) { - if ( pthread_cond_init( &mCondition, NULL ) < 0 ) - throw ThreadException( stringtf( "Unable to create pthread condition: %s", strerror(errno) ) ); + if ( pthread_cond_init( &mCondition, NULL ) < 0 ) + throw ThreadException( stringtf( "Unable to create pthread condition: %s", strerror(errno) ) ); } Condition::~Condition() { - if ( pthread_cond_destroy( &mCondition ) < 0 ) - throw ThreadException( stringtf( "Unable to destroy pthread condition: %s", strerror(errno) ) ); + if ( pthread_cond_destroy( &mCondition ) < 0 ) + throw ThreadException( stringtf( "Unable to destroy pthread condition: %s", strerror(errno) ) ); } void Condition::wait() { - // Locking done outside of this function - if ( pthread_cond_wait( &mCondition, mMutex.getMutex() ) < 0 ) - throw ThreadException( stringtf( "Unable to wait pthread condition: %s", strerror(errno) ) ); + // Locking done outside of this function + if ( pthread_cond_wait( &mCondition, mMutex.getMutex() ) < 0 ) + throw ThreadException( stringtf( "Unable to wait pthread condition: %s", strerror(errno) ) ); } bool Condition::wait( int secs ) { - // Locking done outside of this function - Debug( 8, "Waiting for %d seconds", secs ); - struct timespec timeout = getTimeout( secs ); - if ( pthread_cond_timedwait( &mCondition, mMutex.getMutex(), &timeout ) < 0 && errno != ETIMEDOUT ) - throw ThreadException( stringtf( "Unable to timedwait pthread condition: %s", strerror(errno) ) ); - return( errno != ETIMEDOUT ); + // Locking done outside of this function + Debug( 8, "Waiting for %d seconds", secs ); + struct timespec timeout = getTimeout( secs ); + if ( pthread_cond_timedwait( &mCondition, mMutex.getMutex(), &timeout ) < 0 && errno != ETIMEDOUT ) + throw ThreadException( stringtf( "Unable to timedwait pthread condition: %s", strerror(errno) ) ); + return( errno != ETIMEDOUT ); } bool Condition::wait( double secs ) { - // Locking done outside of this function - struct timespec timeout = getTimeout( secs ); - if ( pthread_cond_timedwait( &mCondition, mMutex.getMutex(), &timeout ) < 0 && errno != ETIMEDOUT ) - throw ThreadException( stringtf( "Unable to timedwait pthread condition: %s", strerror(errno) ) ); - return( errno != ETIMEDOUT ); + // Locking done outside of this function + struct timespec timeout = getTimeout( secs ); + if ( pthread_cond_timedwait( &mCondition, mMutex.getMutex(), &timeout ) < 0 && errno != ETIMEDOUT ) + throw ThreadException( stringtf( "Unable to timedwait pthread condition: %s", strerror(errno) ) ); + return( errno != ETIMEDOUT ); } void Condition::signal() { - if ( pthread_cond_signal( &mCondition ) < 0 ) - throw ThreadException( stringtf( "Unable to signal pthread condition: %s", strerror(errno) ) ); + if ( pthread_cond_signal( &mCondition ) < 0 ) + throw ThreadException( stringtf( "Unable to signal pthread condition: %s", strerror(errno) ) ); } void Condition::broadcast() { - if ( pthread_cond_broadcast( &mCondition ) < 0 ) - throw ThreadException( stringtf( "Unable to broadcast pthread condition: %s", strerror(errno) ) ); + if ( pthread_cond_broadcast( &mCondition ) < 0 ) + throw ThreadException( stringtf( "Unable to broadcast pthread condition: %s", strerror(errno) ) ); } template const T ThreadData::getValue() const { - mMutex.lock(); - const T valueCopy = mValue; - mMutex.unlock(); - return( valueCopy ); + mMutex.lock(); + const T valueCopy = mValue; + mMutex.unlock(); + return( valueCopy ); } template T ThreadData::setValue( const T value ) { - mMutex.lock(); - const T valueCopy = mValue = value; - mMutex.unlock(); - return( valueCopy ); + mMutex.lock(); + const T valueCopy = mValue = value; + mMutex.unlock(); + return( valueCopy ); } template const T ThreadData::getUpdatedValue() const { - Debug( 8, "Waiting for value update, %p", this ); - mMutex.lock(); - mChanged = false; - //do { - mCondition.wait(); - //} while ( !mChanged ); - const T valueCopy = mValue; - mMutex.unlock(); - Debug( 9, "Got value update, %p", this ); - return( valueCopy ); + Debug( 8, "Waiting for value update, %p", this ); + mMutex.lock(); + mChanged = false; + //do { + mCondition.wait(); + //} while ( !mChanged ); + const T valueCopy = mValue; + mMutex.unlock(); + Debug( 9, "Got value update, %p", this ); + return( valueCopy ); } template const T ThreadData::getUpdatedValue( double secs ) const { - Debug( 8, "Waiting for value update, %.2f secs, %p", secs, this ); - mMutex.lock(); - mChanged = false; - //do { - mCondition.wait( secs ); - //} while ( !mChanged ); - const T valueCopy = mValue; - mMutex.unlock(); - Debug( 9, "Got value update, %p", this ); - return( valueCopy ); + Debug( 8, "Waiting for value update, %.2f secs, %p", secs, this ); + mMutex.lock(); + mChanged = false; + //do { + mCondition.wait( secs ); + //} while ( !mChanged ); + const T valueCopy = mValue; + mMutex.unlock(); + Debug( 9, "Got value update, %p", this ); + return( valueCopy ); } template const T ThreadData::getUpdatedValue( int secs ) const { - Debug( 8, "Waiting for value update, %d secs, %p", secs, this ); - mMutex.lock(); - mChanged = false; - //do { - mCondition.wait( secs ); - //} while ( !mChanged ); - const T valueCopy = mValue; - mMutex.unlock(); - Debug( 9, "Got value update, %p", this ); - return( valueCopy ); + Debug( 8, "Waiting for value update, %d secs, %p", secs, this ); + mMutex.lock(); + mChanged = false; + //do { + mCondition.wait( secs ); + //} while ( !mChanged ); + const T valueCopy = mValue; + mMutex.unlock(); + Debug( 9, "Got value update, %p", this ); + return( valueCopy ); } template void ThreadData::updateValueSignal( const T value ) { - Debug( 8, "Updating value with signal, %p", this ); - mMutex.lock(); - mValue = value; - mChanged = true; - mCondition.signal(); - mMutex.unlock(); - Debug( 9, "Updated value, %p", this ); + Debug( 8, "Updating value with signal, %p", this ); + mMutex.lock(); + mValue = value; + mChanged = true; + mCondition.signal(); + mMutex.unlock(); + Debug( 9, "Updated value, %p", this ); } template void ThreadData::updateValueBroadcast( const T value ) { - Debug( 8, "Updating value with broadcast, %p", this ); - mMutex.lock(); - mValue = value; - mChanged = true; - mCondition.broadcast(); - mMutex.unlock(); - Debug( 9, "Updated value, %p", this ); + Debug( 8, "Updating value with broadcast, %p", this ); + mMutex.lock(); + mValue = value; + mChanged = true; + mCondition.broadcast(); + mMutex.unlock(); + Debug( 9, "Updated value, %p", this ); } Thread::Thread() : - mThreadCondition( mThreadMutex ), - mPid( -1 ), - mStarted( false ), - mRunning( false ) + mThreadCondition( mThreadMutex ), + mPid( -1 ), + mStarted( false ), + mRunning( false ) { - Debug( 1, "Creating thread" ); + Debug( 1, "Creating thread" ); } Thread::~Thread() { - Debug( 1, "Destroying thread %d", mPid ); - if ( mStarted ) - join(); + Debug( 1, "Destroying thread %d", mPid ); + if ( mStarted ) + join(); } void *Thread::mThreadFunc( void *arg ) { - Debug( 2, "Invoking thread" ); + Debug( 2, "Invoking thread" ); - Thread *thisPtr = (Thread *)arg; - void *status = 0; - try - { - thisPtr->mThreadMutex.lock(); - thisPtr->mPid = thisPtr->id(); - thisPtr->mThreadCondition.signal(); - thisPtr->mThreadMutex.unlock(); - thisPtr->mRunning = true; - int run=(thisPtr->run()); - status = (void *)&run; - thisPtr->mRunning = false; - Debug( 2, "Exiting thread, status %p", status ); - } - catch ( const ThreadException &e ) - { - Error( "%s", e.getMessage().c_str() ); - thisPtr->mRunning = false; - status = (void *)-1; - Debug( 2, "Exiting thread after exception, status %p", status ); - } - return( status ); + Thread *thisPtr = (Thread *)arg; + void *status = 0; + try + { + thisPtr->mThreadMutex.lock(); + thisPtr->mPid = thisPtr->id(); + thisPtr->mThreadCondition.signal(); + thisPtr->mThreadMutex.unlock(); + thisPtr->mRunning = true; + int run=(thisPtr->run()); + status = (void *)&run; + thisPtr->mRunning = false; + Debug( 2, "Exiting thread, status %p", status ); + } + catch ( const ThreadException &e ) + { + Error( "%s", e.getMessage().c_str() ); + thisPtr->mRunning = false; + status = (void *)-1; + Debug( 2, "Exiting thread after exception, status %p", status ); + } + return( status ); } void Thread::start() { - Debug( 1, "Starting thread" ); - if ( isThread() ) - throw ThreadException( "Can't self start thread" ); - mThreadMutex.lock(); - if ( !mStarted ) - { - pthread_attr_t threadAttrs; - pthread_attr_init( &threadAttrs ); - pthread_attr_setscope( &threadAttrs, PTHREAD_SCOPE_SYSTEM ); + Debug( 1, "Starting thread" ); + if ( isThread() ) + throw ThreadException( "Can't self start thread" ); + mThreadMutex.lock(); + if ( !mStarted ) + { + pthread_attr_t threadAttrs; + pthread_attr_init( &threadAttrs ); + pthread_attr_setscope( &threadAttrs, PTHREAD_SCOPE_SYSTEM ); - mStarted = true; - if ( pthread_create( &mThread, &threadAttrs, mThreadFunc, this ) < 0 ) - throw ThreadException( stringtf( "Can't create thread: %s", strerror(errno) ) ); - pthread_attr_destroy( &threadAttrs ); - } - else - { - Error( "Attempt to start already running thread %d", mPid ); - } - mThreadCondition.wait(); - mThreadMutex.unlock(); - Debug( 1, "Started thread %d", mPid ); + mStarted = true; + if ( pthread_create( &mThread, &threadAttrs, mThreadFunc, this ) < 0 ) + throw ThreadException( stringtf( "Can't create thread: %s", strerror(errno) ) ); + pthread_attr_destroy( &threadAttrs ); + } + else + { + Error( "Attempt to start already running thread %d", mPid ); + } + mThreadCondition.wait(); + mThreadMutex.unlock(); + Debug( 1, "Started thread %d", mPid ); } void Thread::join() { - Debug( 1, "Joining thread %d", mPid ); - if ( isThread() ) - throw ThreadException( "Can't self join thread" ); - mThreadMutex.lock(); - if ( mPid >= 0 ) + Debug( 1, "Joining thread %d", mPid ); + if ( isThread() ) + throw ThreadException( "Can't self join thread" ); + mThreadMutex.lock(); + if ( mPid >= 0 ) + { + if ( mStarted ) { - if ( mStarted ) - { - void *threadStatus = 0; - if ( pthread_join( mThread, &threadStatus ) < 0 ) - throw ThreadException( stringtf( "Can't join sender thread: %s", strerror(errno) ) ); - mStarted = false; - Debug( 1, "Thread %d exited, status %p", mPid, threadStatus ); - } - else - { - Warning( "Attempt to join already finished thread %d", mPid ); - } + void *threadStatus = 0; + if ( pthread_join( mThread, &threadStatus ) < 0 ) + throw ThreadException( stringtf( "Can't join sender thread: %s", strerror(errno) ) ); + mStarted = false; + Debug( 1, "Thread %d exited, status %p", mPid, threadStatus ); } else { - Warning( "Attempt to join non-started thread %d", mPid ); + Warning( "Attempt to join already finished thread %d", mPid ); } - mThreadMutex.unlock(); - Debug( 1, "Joined thread %d", mPid ); + } + else + { + Warning( "Attempt to join non-started thread %d", mPid ); + } + mThreadMutex.unlock(); + Debug( 1, "Joined thread %d", mPid ); } void Thread::kill( int signal ) { - pthread_kill( mThread, signal ); + pthread_kill( mThread, signal ); } // Some explicit template instantiations diff --git a/src/zm_thread.h b/src/zm_thread.h index 615bec6aa..685148ea8 100644 --- a/src/zm_thread.h +++ b/src/zm_thread.h @@ -36,27 +36,27 @@ class ThreadException : public Exception { private: #ifndef SOLARIS -pid_t pid() { + pid_t pid() { pid_t tid; #ifdef __FreeBSD__ long lwpid; thr_self(&lwpid); tid = lwpid; #else - #ifdef __FreeBSD_kernel__ - if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id - # else - tid=syscall(SYS_gettid); - #endif + #ifdef __FreeBSD_kernel__ + if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id + # else + tid=syscall(SYS_gettid); + #endif #endif return tid; -} + } #else -pthread_t pid() { return( pthread_self() ); } + pthread_t pid() { return( pthread_self() ); } #endif public: - ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) { - } + ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) { + } }; class Mutex @@ -64,214 +64,214 @@ class Mutex friend class Condition; private: - pthread_mutex_t mMutex; + pthread_mutex_t mMutex; public: - Mutex(); - ~Mutex(); + Mutex(); + ~Mutex(); private: - pthread_mutex_t *getMutex() - { - return( &mMutex ); - } + pthread_mutex_t *getMutex() + { + return( &mMutex ); + } public: - void lock(); - void lock( int secs ); - void lock( double secs ); - void unlock(); - bool locked(); + void lock(); + void lock( int secs ); + void lock( double secs ); + void unlock(); + bool locked(); }; class ScopedMutex { private: - Mutex &mMutex; + Mutex &mMutex; public: - ScopedMutex( Mutex &mutex ) : mMutex( mutex ) - { - mMutex.lock(); - } - ~ScopedMutex() - { - mMutex.unlock(); - } + ScopedMutex( Mutex &mutex ) : mMutex( mutex ) + { + mMutex.lock(); + } + ~ScopedMutex() + { + mMutex.unlock(); + } private: - ScopedMutex( const ScopedMutex & ); + ScopedMutex( const ScopedMutex & ); }; class Condition { private: - Mutex &mMutex; - pthread_cond_t mCondition; + Mutex &mMutex; + pthread_cond_t mCondition; public: - Condition( Mutex &mutex ); - ~Condition(); + Condition( Mutex &mutex ); + ~Condition(); - void wait(); - bool wait( int secs ); - bool wait( double secs ); - void signal(); - void broadcast(); + void wait(); + bool wait( int secs ); + bool wait( double secs ); + void signal(); + void broadcast(); }; class Semaphore : public Condition { private: - Mutex mMutex; + Mutex mMutex; public: - Semaphore() : Condition( mMutex ) - { - } + Semaphore() : Condition( mMutex ) + { + } - void wait() - { - mMutex.lock(); - Condition::wait(); - mMutex.unlock(); - } - bool wait( int secs ) - { - mMutex.lock(); - bool result = Condition::wait( secs ); - mMutex.unlock(); - return( result ); - } - bool wait( double secs ) - { - mMutex.lock(); - bool result = Condition::wait( secs ); - mMutex.unlock(); - return( result ); - } - void signal() - { - mMutex.lock(); - Condition::signal(); - mMutex.unlock(); - } - void broadcast() - { - mMutex.lock(); - Condition::broadcast(); - mMutex.unlock(); - } + void wait() + { + mMutex.lock(); + Condition::wait(); + mMutex.unlock(); + } + bool wait( int secs ) + { + mMutex.lock(); + bool result = Condition::wait( secs ); + mMutex.unlock(); + return( result ); + } + bool wait( double secs ) + { + mMutex.lock(); + bool result = Condition::wait( secs ); + mMutex.unlock(); + return( result ); + } + void signal() + { + mMutex.lock(); + Condition::signal(); + mMutex.unlock(); + } + void broadcast() + { + mMutex.lock(); + Condition::broadcast(); + mMutex.unlock(); + } }; template class ThreadData { private: - T mValue; - mutable bool mChanged; - mutable Mutex mMutex; - mutable Condition mCondition; + T mValue; + mutable bool mChanged; + mutable Mutex mMutex; + mutable Condition mCondition; public: - __attribute__((used)) ThreadData() : mCondition( mMutex ) - { - } - __attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex ) - { - } - //~ThreadData() {} + __attribute__((used)) ThreadData() : mCondition( mMutex ) + { + } + __attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex ) + { + } + //~ThreadData() {} - __attribute__((used)) operator T() const - { - return( getValue() ); - } - __attribute__((used)) const T operator=( const T value ) - { - return( setValue( value ) ); - } + __attribute__((used)) operator T() const + { + return( getValue() ); + } + __attribute__((used)) const T operator=( const T value ) + { + return( setValue( value ) ); + } - __attribute__((used)) const T getValueImmediate() const - { - return( mValue ); - } - __attribute__((used)) T setValueImmediate( const T value ) - { - return( mValue = value ); - } - __attribute__((used)) const T getValue() const; - __attribute__((used)) T setValue( const T value ); - __attribute__((used)) const T getUpdatedValue() const; - __attribute__((used)) const T getUpdatedValue( double secs ) const; - __attribute__((used)) const T getUpdatedValue( int secs ) const; - __attribute__((used)) void updateValueSignal( const T value ); - __attribute__((used)) void updateValueBroadcast( const T value ); + __attribute__((used)) const T getValueImmediate() const + { + return( mValue ); + } + __attribute__((used)) T setValueImmediate( const T value ) + { + return( mValue = value ); + } + __attribute__((used)) const T getValue() const; + __attribute__((used)) T setValue( const T value ); + __attribute__((used)) const T getUpdatedValue() const; + __attribute__((used)) const T getUpdatedValue( double secs ) const; + __attribute__((used)) const T getUpdatedValue( int secs ) const; + __attribute__((used)) void updateValueSignal( const T value ); + __attribute__((used)) void updateValueBroadcast( const T value ); }; class Thread { public: - typedef void *(*ThreadFunc)( void * ); + typedef void *(*ThreadFunc)( void * ); protected: - pthread_t mThread; + pthread_t mThread; - Mutex mThreadMutex; - Condition mThreadCondition; + Mutex mThreadMutex; + Condition mThreadCondition; #ifndef SOLARIS - pid_t mPid; + pid_t mPid; #else - pthread_t mPid; + pthread_t mPid; #endif - bool mStarted; - bool mRunning; + bool mStarted; + bool mRunning; protected: - Thread(); - virtual ~Thread(); + Thread(); + virtual ~Thread(); #ifndef SOLARIS - pid_t id() const - { - pid_t tid; + pid_t id() const + { + pid_t tid; #ifdef __FreeBSD__ - long lwpid; - thr_self(&lwpid); - tid = lwpid; + long lwpid; + thr_self(&lwpid); + tid = lwpid; #else - #ifdef __FreeBSD_kernel__ - if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id + #ifdef __FreeBSD_kernel__ + if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id - #else - tid=syscall(SYS_gettid); - #endif + #else + tid=syscall(SYS_gettid); + #endif #endif return tid; - } + } #else - pthread_t id() const - { - return( pthread_self() ); - } + pthread_t id() const + { + return( pthread_self() ); + } #endif - void exit( int status = 0 ) - { - //INFO( "Exiting" ); - pthread_exit( (void *)&status ); - } - static void *mThreadFunc( void *arg ); + void exit( int status = 0 ) + { + //INFO( "Exiting" ); + pthread_exit( (void *)&status ); + } + static void *mThreadFunc( void *arg ); public: - virtual int run() = 0; + virtual int run() = 0; - void start(); - void join(); - void kill( int signal ); - bool isThread() - { - return( mPid > -1 && pthread_equal( pthread_self(), mThread ) ); - } - bool isStarted() const { return( mStarted ); } - bool isRunning() const { return( mRunning ); } + void start(); + void join(); + void kill( int signal ); + bool isThread() + { + return( mPid > -1 && pthread_equal( pthread_self(), mThread ) ); + } + bool isStarted() const { return( mStarted ); } + bool isRunning() const { return( mRunning ); } }; #endif // ZM_THREAD_H diff --git a/src/zm_time.h b/src/zm_time.h index 646133feb..df79e7fff 100644 --- a/src/zm_time.h +++ b/src/zm_time.h @@ -29,48 +29,48 @@ struct DeltaTimeval { - bool positive; - unsigned long delta; - unsigned long sec; - unsigned long fsec; - unsigned long prec; + bool positive; + unsigned long delta; + unsigned long sec; + unsigned long fsec; + unsigned long prec; }; -#define DT_GRAN_1000000 1000000 -#define DT_PREC_6 DT_GRAN_1000000 -#define DT_GRAN_100000 100000 -#define DT_PREC_5 DT_GRAN_100000 -#define DT_GRAN_10000 10000 -#define DT_PREC_4 DT_GRAN_10000 -#define DT_GRAN_1000 1000 -#define DT_PREC_3 DT_GRAN_1000 -#define DT_GRAN_100 100 -#define DT_PREC_2 DT_GRAN_100 -#define DT_GRAN_10 10 -#define DT_PREC_1 DT_GRAN_10 +#define DT_GRAN_1000000 1000000 +#define DT_PREC_6 DT_GRAN_1000000 +#define DT_GRAN_100000 100000 +#define DT_PREC_5 DT_GRAN_100000 +#define DT_GRAN_10000 10000 +#define DT_PREC_4 DT_GRAN_10000 +#define DT_GRAN_1000 1000 +#define DT_PREC_3 DT_GRAN_1000 +#define DT_GRAN_100 100 +#define DT_PREC_2 DT_GRAN_100 +#define DT_GRAN_10 10 +#define DT_PREC_1 DT_GRAN_10 -#define DT_MAXGRAN DT_GRAN_1000000 +#define DT_MAXGRAN DT_GRAN_1000000 // This obviously wouldn't work for massive deltas but as it's mostly // for frames it will only usually be a fraction of a second or so #define DELTA_TIMEVAL( result, time1, time2, precision ) \ { \ - int delta = (((time1).tv_sec-(time2).tv_sec)*(precision))+(((time1).tv_usec-(time2).tv_usec)/(DT_MAXGRAN/(precision))); \ - result.positive = (delta>=0); \ - result.delta = abs(delta); \ - result.sec = result.delta/(precision); \ - result.fsec = result.delta%(precision); \ - result.prec = (precision); \ + int delta = (((time1).tv_sec-(time2).tv_sec)*(precision))+(((time1).tv_usec-(time2).tv_usec)/(DT_MAXGRAN/(precision))); \ + result.positive = (delta>=0); \ + result.delta = abs(delta); \ + result.sec = result.delta/(precision); \ + result.fsec = result.delta%(precision); \ + result.prec = (precision); \ } #define TIMEVAL_INTERVAL( result, time1, time2, precision ) \ { \ - int delta = (((time1).tv_sec-(time2).tv_sec)*(precision))+(((time1).tv_usec-(time2).tv_usec)/(DT_MAXGRAN/(precision))); \ - result.positive = (delta>=0); \ - result.delta = abs(delta); \ - result.sec = result.delta/(precision); \ - result.fsec = result.delta%(precision); \ - result.prec = (precision); \ + int delta = (((time1).tv_sec-(time2).tv_sec)*(precision))+(((time1).tv_usec-(time2).tv_usec)/(DT_MAXGRAN/(precision))); \ + result.positive = (delta>=0); \ + result.delta = abs(delta); \ + result.sec = result.delta/(precision); \ + result.fsec = result.delta%(precision); \ + result.prec = (precision); \ } #define USEC_PER_SEC 1000000 @@ -82,128 +82,128 @@ typedef typeof(tv.tv_usec) ast_suseconds_t; inline int tvDiffUsec( struct timeval first, struct timeval last ) { - return( (last.tv_sec - first.tv_sec) * USEC_PER_SEC) + ((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC ); + return( (last.tv_sec - first.tv_sec) * USEC_PER_SEC) + ((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC ); } inline int tvDiffUsec( struct timeval first ) { - struct timeval now; - gettimeofday( &now, NULL ); - return( tvDiffUsec( first, now ) ); + struct timeval now; + gettimeofday( &now, NULL ); + return( tvDiffUsec( first, now ) ); } inline int tvDiffMsec( struct timeval first, struct timeval last ) { - return( (last.tv_sec - first.tv_sec) * MSEC_PER_SEC) + (((MSEC_PER_SEC + last.tv_usec - first.tv_usec) / MSEC_PER_SEC) - MSEC_PER_SEC ); + return( (last.tv_sec - first.tv_sec) * MSEC_PER_SEC) + (((MSEC_PER_SEC + last.tv_usec - first.tv_usec) / MSEC_PER_SEC) - MSEC_PER_SEC ); } inline int tvDiffMsec( struct timeval first ) { - struct timeval now; - gettimeofday( &now, NULL ); - return( tvDiffMsec( first, now ) ); + struct timeval now; + gettimeofday( &now, NULL ); + return( tvDiffMsec( first, now ) ); } inline double tvDiffSec( struct timeval first, struct timeval last ) { - return( double(last.tv_sec - first.tv_sec) + double(((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC) / (1.0*USEC_PER_SEC) ) ); + return( double(last.tv_sec - first.tv_sec) + double(((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC) / (1.0*USEC_PER_SEC) ) ); } inline double tvDiffSec( struct timeval first ) { - struct timeval now; - gettimeofday( &now, NULL ); - return( tvDiffSec( first, now ) ); + struct timeval now; + gettimeofday( &now, NULL ); + return( tvDiffSec( first, now ) ); } inline struct timeval tvZero() { - struct timeval t = { 0, 0 }; - return( t ); + struct timeval t = { 0, 0 }; + return( t ); } inline int tvIsZero( const struct timeval t ) { - return( t.tv_sec == 0 && t.tv_usec == 0 ); + return( t.tv_sec == 0 && t.tv_usec == 0 ); } inline int tvCmp( struct timeval t1, struct timeval t2 ) { - if ( t1.tv_sec < t2.tv_sec ) - return( -1 ); - if ( t1.tv_sec > t2.tv_sec ) - return( 1 ); - if ( t1.tv_usec < t2.tv_usec ) - return( -1 ); - if ( t1.tv_usec > t2.tv_usec ) - return( 1 ); - return( 0 ); + if ( t1.tv_sec < t2.tv_sec ) + return( -1 ); + if ( t1.tv_sec > t2.tv_sec ) + return( 1 ); + if ( t1.tv_usec < t2.tv_usec ) + return( -1 ); + if ( t1.tv_usec > t2.tv_usec ) + return( 1 ); + return( 0 ); } inline int tvEq( struct timeval t1, struct timeval t2 ) { - return( t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec ); + return( t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec ); } inline struct timeval tvNow( void ) { - struct timeval t; - gettimeofday( &t, NULL ); - return( t ); + struct timeval t; + gettimeofday( &t, NULL ); + return( t ); } inline struct timeval tvCheck( struct timeval &t ) { - if ( t.tv_usec >= USEC_PER_SEC ) - { - Warning( "Timestamp too large %ld.%ld\n", t.tv_sec, (long int) t.tv_usec ); - t.tv_sec += t.tv_usec / USEC_PER_SEC; - t.tv_usec %= USEC_PER_SEC; - } - else if ( t.tv_usec < 0 ) - { - Warning( "Got negative timestamp %ld.%ld\n", t.tv_sec, (long int)t.tv_usec ); - t.tv_usec = 0; - } - return( t ); + if ( t.tv_usec >= USEC_PER_SEC ) + { + Warning( "Timestamp too large %ld.%ld\n", t.tv_sec, (long int) t.tv_usec ); + t.tv_sec += t.tv_usec / USEC_PER_SEC; + t.tv_usec %= USEC_PER_SEC; + } + else if ( t.tv_usec < 0 ) + { + Warning( "Got negative timestamp %ld.%ld\n", t.tv_sec, (long int)t.tv_usec ); + t.tv_usec = 0; + } + return( t ); } // Add t2 to t1 inline struct timeval tvAdd( struct timeval t1, struct timeval t2 ) { - tvCheck(t1); - tvCheck(t2); - t1.tv_sec += t2.tv_sec; - t1.tv_usec += t2.tv_usec; - if ( t1.tv_usec >= USEC_PER_SEC ) - { - t1.tv_sec++; - t1.tv_usec -= USEC_PER_SEC; - } - return( t1 ); + tvCheck(t1); + tvCheck(t2); + t1.tv_sec += t2.tv_sec; + t1.tv_usec += t2.tv_usec; + if ( t1.tv_usec >= USEC_PER_SEC ) + { + t1.tv_sec++; + t1.tv_usec -= USEC_PER_SEC; + } + return( t1 ); } // Subtract t2 from t1 inline struct timeval tvSub( struct timeval t1, struct timeval t2 ) { - tvCheck(t1); - tvCheck(t2); - t1.tv_sec -= t2.tv_sec; - t1.tv_usec -= t2.tv_usec; - if ( t1.tv_usec < 0 ) - { - t1.tv_sec--; - t1.tv_usec += USEC_PER_SEC; - } - return( t1 ) ; + tvCheck(t1); + tvCheck(t2); + t1.tv_sec -= t2.tv_sec; + t1.tv_usec -= t2.tv_usec; + if ( t1.tv_usec < 0 ) + { + t1.tv_sec--; + t1.tv_usec += USEC_PER_SEC; + } + return( t1 ) ; } inline struct timeval tvMake( time_t sec, suseconds_t usec ) { - struct timeval t; - t.tv_sec = sec; - t.tv_usec = usec; - return( t ); + struct timeval t; + t.tv_sec = sec; + t.tv_usec = usec; + return( t ); } #endif // ZM_TIME_H diff --git a/src/zm_timer.cpp b/src/zm_timer.cpp index fbac45435..a067308b7 100644 --- a/src/zm_timer.cpp +++ b/src/zm_timer.cpp @@ -24,96 +24,96 @@ int Timer::TimerThread::mNextTimerId = 0; Timer::TimerThread::TimerThread( Timer &timer, int duration, bool repeat ) : - mTimerId( 0 ), - mTimer( timer ), - mDuration( duration ), - mRepeat( repeat ), - mReset( false ), - mExpiryFlag( true ) + mTimerId( 0 ), + mTimer( timer ), + mDuration( duration ), + mRepeat( repeat ), + mReset( false ), + mExpiryFlag( true ) { - mAccessMutex.lock(); - mTimerId = mNextTimerId++; - Debug( 5, "Creating timer %d for %d seconds%s", mTimerId, mDuration, mRepeat?", repeating":"" ); - mAccessMutex.unlock(); + mAccessMutex.lock(); + mTimerId = mNextTimerId++; + Debug( 5, "Creating timer %d for %d seconds%s", mTimerId, mDuration, mRepeat?", repeating":"" ); + mAccessMutex.unlock(); } Timer::TimerThread::~TimerThread() { - cancel(); + cancel(); } void Timer::TimerThread::cancel() { - mAccessMutex.lock(); - if ( mRunning ) - { - Debug( 4, "Cancelling timer %d", mTimerId ); - mRepeat = false; - mReset = false; - mExpiryFlag.updateValueSignal( false ); - } - mAccessMutex.unlock(); + mAccessMutex.lock(); + if ( mRunning ) + { + Debug( 4, "Cancelling timer %d", mTimerId ); + mRepeat = false; + mReset = false; + mExpiryFlag.updateValueSignal( false ); + } + mAccessMutex.unlock(); } void Timer::TimerThread::reset() { - mAccessMutex.lock(); - if ( mRunning ) - { - Debug( 4, "Resetting timer" ); - mReset = true; - mExpiryFlag.updateValueSignal( false ); - } - else - { - Error( "Attempting to reset expired timer %d", mTimerId ); - } - mAccessMutex.unlock(); + mAccessMutex.lock(); + if ( mRunning ) + { + Debug( 4, "Resetting timer" ); + mReset = true; + mExpiryFlag.updateValueSignal( false ); + } + else + { + Error( "Attempting to reset expired timer %d", mTimerId ); + } + mAccessMutex.unlock(); } int Timer::TimerThread::run() { - Debug( 4, "Starting timer %d for %d seconds", mTimerId, mDuration ); - bool timerExpired = false; - do + Debug( 4, "Starting timer %d for %d seconds", mTimerId, mDuration ); + bool timerExpired = false; + do + { + mAccessMutex.lock(); + mReset = false; + mExpiryFlag.setValue( true ); + mAccessMutex.unlock(); + timerExpired = mExpiryFlag.getUpdatedValue( mDuration ); + mAccessMutex.lock(); + if ( timerExpired ) { - mAccessMutex.lock(); - mReset = false; - mExpiryFlag.setValue( true ); - mAccessMutex.unlock(); - timerExpired = mExpiryFlag.getUpdatedValue( mDuration ); - mAccessMutex.lock(); - if ( timerExpired ) - { - Debug( 4, "Timer %d expired", mTimerId ); - mTimer.expire(); - } - else - { - Debug( 4, "Timer %d %s", mTimerId, mReset?"reset":"cancelled" ); - } - mAccessMutex.unlock(); - } while ( mRepeat || (mReset && !timerExpired) ); - return( timerExpired ); + Debug( 4, "Timer %d expired", mTimerId ); + mTimer.expire(); + } + else + { + Debug( 4, "Timer %d %s", mTimerId, mReset?"reset":"cancelled" ); + } + mAccessMutex.unlock(); + } while ( mRepeat || (mReset && !timerExpired) ); + return( timerExpired ); } Timer::Timer( int timeout, bool repeat ) : mTimerThread( *this, timeout, repeat ) { - mTimerThread.start(); + mTimerThread.start(); } Timer::~Timer() { - //cancel(); + //cancel(); } void Timer::Timer::cancel() { - mTimerThread.cancel(); + mTimerThread.cancel(); } void Timer::Timer::reset() { - mTimerThread.reset(); + mTimerThread.reset(); } diff --git a/src/zm_timer.h b/src/zm_timer.h index 7afe0a647..2213d3cd0 100644 --- a/src/zm_timer.h +++ b/src/zm_timer.h @@ -30,81 +30,81 @@ class Timer { private: - class TimerException : public Exception - { - private: + class TimerException : public Exception + { + private: #ifndef SOLARIS - pid_t pid() { - pid_t tid; + pid_t pid() { + pid_t tid; #ifdef __FreeBSD__ - long lwpid; - thr_self(&lwpid); - tid = lwpid; + long lwpid; + thr_self(&lwpid); + tid = lwpid; #else - #ifdef __FreeBSD_kernel__ - if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id - #else - tid=syscall(SYS_gettid); - #endif + #ifdef __FreeBSD_kernel__ + if ( (syscall(SYS_thr_self, &tid)) < 0 ) // Thread/Process id + #else + tid=syscall(SYS_gettid); + #endif #endif - return tid; - } + return tid; + } #else - pthread_t pid() { return( pthread_self() ); } + pthread_t pid() { return( pthread_self() ); } #endif - public: - TimerException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) - { - } - }; - - class TimerThread : public Thread + public: + TimerException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)pid() ) ) { - private: - typedef ThreadData ExpiryFlag; + } + }; - private: - static int mNextTimerId; + class TimerThread : public Thread + { + private: + typedef ThreadData ExpiryFlag; - private: - int mTimerId; - Timer &mTimer; - int mDuration; - int mRepeat; - int mReset; - ExpiryFlag mExpiryFlag; - Mutex mAccessMutex; + private: + static int mNextTimerId; - private: - void quit() - { - cancel(); - } + private: + int mTimerId; + Timer &mTimer; + int mDuration; + int mRepeat; + int mReset; + ExpiryFlag mExpiryFlag; + Mutex mAccessMutex; - public: - TimerThread( Timer &timer, int timeout, bool repeat ); - ~TimerThread(); + private: + void quit() + { + cancel(); + } - void cancel(); - void reset(); - int run(); - }; + public: + TimerThread( Timer &timer, int timeout, bool repeat ); + ~TimerThread(); -protected: - TimerThread mTimerThread; - -protected: - Timer( int timeout, bool repeat=false ); - -public: - virtual ~Timer(); - -protected: - virtual void expire()=0; - -public: void cancel(); void reset(); + int run(); + }; + +protected: + TimerThread mTimerThread; + +protected: + Timer( int timeout, bool repeat=false ); + +public: + virtual ~Timer(); + +protected: + virtual void expire()=0; + +public: + void cancel(); + void reset(); }; #endif // ZM_TIMER_H diff --git a/src/zm_user.cpp b/src/zm_user.cpp index f7822044c..73f5c7932 100644 --- a/src/zm_user.cpp +++ b/src/zm_user.cpp @@ -29,119 +29,119 @@ User::User() { - username[0] = password[0] = 0; - enabled = false; - stream = events = control = monitors = system = PERM_NONE; - monitor_ids = 0; + username[0] = password[0] = 0; + enabled = false; + stream = events = control = monitors = system = PERM_NONE; + monitor_ids = 0; } User::User( MYSQL_ROW &dbrow ) { - int index = 0; - strncpy( username, dbrow[index++], sizeof(username) ); - strncpy( password, dbrow[index++], sizeof(password) ); - enabled = (bool)atoi( dbrow[index++] ); - stream = (Permission)atoi( dbrow[index++] ); - events = (Permission)atoi( dbrow[index++] ); - control = (Permission)atoi( dbrow[index++] ); - monitors = (Permission)atoi( dbrow[index++] ); - system = (Permission)atoi( dbrow[index++] ); - monitor_ids = 0; - char *monitor_ids_str = dbrow[index++]; - if ( monitor_ids_str && *monitor_ids_str ) - { - monitor_ids = new int[strlen(monitor_ids_str)]; - int n_monitor_ids = 0; - const char *ptr = monitor_ids_str; - do - { - int id = 0; - while( isdigit( *ptr ) ) - { - id *= 10; - id += *ptr-'0'; - ptr++; - } - if ( id ) - { - monitor_ids[n_monitor_ids++] = id; - if ( !*ptr ) - break; - } - while ( !isdigit( *ptr ) ) - ptr++; - } while( *ptr ); - monitor_ids[n_monitor_ids] = 0; - } + int index = 0; + strncpy( username, dbrow[index++], sizeof(username) ); + strncpy( password, dbrow[index++], sizeof(password) ); + enabled = (bool)atoi( dbrow[index++] ); + stream = (Permission)atoi( dbrow[index++] ); + events = (Permission)atoi( dbrow[index++] ); + control = (Permission)atoi( dbrow[index++] ); + monitors = (Permission)atoi( dbrow[index++] ); + system = (Permission)atoi( dbrow[index++] ); + monitor_ids = 0; + char *monitor_ids_str = dbrow[index++]; + if ( monitor_ids_str && *monitor_ids_str ) + { + monitor_ids = new int[strlen(monitor_ids_str)]; + int n_monitor_ids = 0; + const char *ptr = monitor_ids_str; + do + { + int id = 0; + while( isdigit( *ptr ) ) + { + id *= 10; + id += *ptr-'0'; + ptr++; + } + if ( id ) + { + monitor_ids[n_monitor_ids++] = id; + if ( !*ptr ) + break; + } + while ( !isdigit( *ptr ) ) + ptr++; + } while( *ptr ); + monitor_ids[n_monitor_ids] = 0; + } } User::~User() { - delete monitor_ids; + delete monitor_ids; } bool User::canAccess( int monitor_id ) { - if ( !monitor_ids ) - { - return( true ); - } - for ( int i = 0; monitor_ids[i]; i++ ) - { - if ( monitor_ids[i] == monitor_id ) - { - return( true ); - } - } - return( false ); + if ( !monitor_ids ) + { + return( true ); + } + for ( int i = 0; monitor_ids[i]; i++ ) + { + if ( monitor_ids[i] == monitor_id ) + { + return( true ); + } + } + return( false ); } // Function to load a user from username and password // Please note that in auth relay mode = none, password is NULL User *zmLoadUser( const char *username, const char *password ) { - char sql[ZM_SQL_SML_BUFSIZ] = ""; - char safer_username[65]; // current db username size is 32 - char safer_password[129]; // current db password size is 64 + char sql[ZM_SQL_SML_BUFSIZ] = ""; + char safer_username[65]; // current db username size is 32 + char safer_password[129]; // current db password size is 64 - // According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator. - mysql_real_escape_string(&dbconn, safer_username, username, strlen( username ) ); + // According to docs, size of safer_whatever must be 2*length+1 due to unicode conversions + null terminator. + mysql_real_escape_string(&dbconn, safer_username, username, strlen( username ) ); - if ( password ) { - mysql_real_escape_string(&dbconn, safer_password, password, strlen( password ) ); - snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password ); - } else { - snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", safer_username ); - } + if ( password ) { + mysql_real_escape_string(&dbconn, safer_password, password, strlen( password ) ); + snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", safer_username, safer_password ); + } else { + snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", safer_username ); + } - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_users = mysql_num_rows( result ); + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_users = mysql_num_rows( result ); - if ( n_users != 1 ) - { - Warning( "Unable to authenticate user %s", username ); - return( 0 ); - } + if ( n_users != 1 ) + { + Warning( "Unable to authenticate user %s", username ); + return( 0 ); + } - MYSQL_ROW dbrow = mysql_fetch_row( result ); + MYSQL_ROW dbrow = mysql_fetch_row( result ); - User *user = new User( dbrow ); - Info( "Authenticated user '%s'", user->getUsername() ); + User *user = new User( dbrow ); + Info( "Authenticated user '%s'", user->getUsername() ); - mysql_free_result( result ); + mysql_free_result( result ); - return( user ); + return( user ); } // Function to validate an authentication string @@ -149,102 +149,102 @@ User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT #ifdef HAVE_GCRYPT_H - // Special initialisation for libgcrypt - if ( !gcry_check_version( GCRYPT_VERSION ) ) - { - Fatal( "Unable to initialise libgcrypt" ); - } - gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); - gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); + // Special initialisation for libgcrypt + if ( !gcry_check_version( GCRYPT_VERSION ) ) + { + Fatal( "Unable to initialise libgcrypt" ); + } + gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); + gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); #endif // HAVE_GCRYPT_H - const char *remote_addr = ""; - if ( use_remote_addr ) - { - remote_addr = getenv( "REMOTE_ADDR" ); - if ( !remote_addr ) - { - Warning( "Can't determine remote address, using null" ); - remote_addr = ""; - } - } + const char *remote_addr = ""; + if ( use_remote_addr ) + { + remote_addr = getenv( "REMOTE_ADDR" ); + if ( !remote_addr ) + { + Warning( "Can't determine remote address, using null" ); + remote_addr = ""; + } + } - Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); - char sql[ZM_SQL_SML_BUFSIZ] = ""; - snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1" ); + Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); + char sql[ZM_SQL_SML_BUFSIZ] = ""; + snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1" ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_users = mysql_num_rows( result ); + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_users = mysql_num_rows( result ); - if ( n_users < 1 ) - { - Warning( "Unable to authenticate user" ); - return( 0 ); - } + if ( n_users < 1 ) + { + Warning( "Unable to authenticate user" ); + return( 0 ); + } - while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) - { - const char *user = dbrow[0]; - const char *pass = dbrow[1]; + while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + const char *user = dbrow[0]; + const char *pass = dbrow[1]; - char auth_key[512] = ""; - char auth_md5[32+1] = ""; - size_t md5len = 16; - unsigned char md5sum[md5len]; + char auth_key[512] = ""; + char auth_md5[32+1] = ""; + size_t md5len = 16; + unsigned char md5sum[md5len]; - time_t now = time( 0 ); - int max_tries = 2; + time_t now = time( 0 ); + int max_tries = 2; - for ( int i = 0; i < max_tries; i++, now -= (60*60) ) - { - struct tm *now_tm = localtime( &now ); + for ( int i = 0; i < max_tries; i++, now -= (60*60) ) + { + struct tm *now_tm = localtime( &now ); - snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d", - config.auth_hash_secret, - user, - pass, - remote_addr, - now_tm->tm_hour, - now_tm->tm_mday, - now_tm->tm_mon, - now_tm->tm_year - ); + snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d", + config.auth_hash_secret, + user, + pass, + remote_addr, + now_tm->tm_hour, + now_tm->tm_mday, + now_tm->tm_mon, + now_tm->tm_year + ); #if HAVE_DECL_MD5 - MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum ); + MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum ); #elif HAVE_DECL_GNUTLS_FINGERPRINT - gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) }; - gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); + gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) }; + gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); #endif - auth_md5[0] = '\0'; - for ( unsigned int j = 0; j < md5len; j++ ) - { - sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); - } - Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s'", auth_key, auth_md5 ); + auth_md5[0] = '\0'; + for ( unsigned int j = 0; j < md5len; j++ ) + { + sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); + } + Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s'", auth_key, auth_md5 ); - if ( !strcmp( auth, auth_md5 ) ) - { - // We have a match - User *user = new User( dbrow ); - Debug(1, "Authenticated user '%s'", user->getUsername() ); - return( user ); - } - } - } + if ( !strcmp( auth, auth_md5 ) ) + { + // We have a match + User *user = new User( dbrow ); + Debug(1, "Authenticated user '%s'", user->getUsername() ); + return( user ); + } + } + } #else // HAVE_DECL_MD5 - Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); + Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); #endif // HAVE_DECL_MD5 - return( 0 ); + return( 0 ); } diff --git a/src/zm_user.h b/src/zm_user.h index 95fb71474..09f5a2f0a 100644 --- a/src/zm_user.h +++ b/src/zm_user.h @@ -39,33 +39,33 @@ class User { public: - typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission; + typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission; protected: - char username[32+1]; - char password[64+1]; - bool enabled; - Permission stream; - Permission events; - Permission control; - Permission monitors; - Permission system; - int *monitor_ids; + char username[32+1]; + char password[64+1]; + bool enabled; + Permission stream; + Permission events; + Permission control; + Permission monitors; + Permission system; + int *monitor_ids; public: - User(); - User( MYSQL_ROW &dbrow ); - ~User(); + User(); + User( MYSQL_ROW &dbrow ); + ~User(); - const char *getUsername() const { return( username ); } - const char *getPassword() const { return( password ); } - bool isEnabled() const { return( enabled ); } - Permission getStream() const { return( stream ); } - Permission getEvents() const { return( events ); } - Permission getControl() const { return( control ); } - Permission getMonitors() const { return( monitors ); } - Permission getSystem() const { return( system ); } - bool canAccess( int monitor_id ); + const char *getUsername() const { return( username ); } + const char *getPassword() const { return( password ); } + bool isEnabled() const { return( enabled ); } + Permission getStream() const { return( stream ); } + Permission getEvents() const { return( events ); } + Permission getControl() const { return( control ); } + Permission getMonitors() const { return( monitors ); } + Permission getSystem() const { return( system ); } + bool canAccess( int monitor_id ); }; User *zmLoadUser( const char *username, const char *password=0 ); diff --git a/src/zm_utils.cpp b/src/zm_utils.cpp index e0c65ca61..67af64a66 100644 --- a/src/zm_utils.cpp +++ b/src/zm_utils.cpp @@ -28,256 +28,256 @@ unsigned int sseversion = 0; std::string trimSet(std::string str, std::string trimset) { - // Trim Both leading and trailing sets - size_t startpos = str.find_first_not_of(trimset); // Find the first character position after excluding leading blank spaces - size_t endpos = str.find_last_not_of(trimset); // Find the first character position from reverse af + // Trim Both leading and trailing sets + size_t startpos = str.find_first_not_of(trimset); // Find the first character position after excluding leading blank spaces + size_t endpos = str.find_last_not_of(trimset); // Find the first character position from reverse af - // if all spaces or empty return an empty string - if(( std::string::npos == startpos ) || ( std::string::npos == endpos)) - { - return std::string(""); - } - else - return str.substr( startpos, endpos-startpos+1 ); + // if all spaces or empty return an empty string + if(( std::string::npos == startpos ) || ( std::string::npos == endpos)) + { + return std::string(""); + } + else + return str.substr( startpos, endpos-startpos+1 ); } std::string trimSpaces(std::string str) { - return trimSet(str, " \t"); + return trimSet(str, " \t"); } std::string replaceAll(std::string str, std::string from, std::string to) { - if(from.empty()) - return str; - size_t start_pos = 0; - while((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' - } + if(from.empty()) return str; + size_t start_pos = 0; + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' + } + return str; } const std::string stringtf( const char *format, ... ) { - va_list ap; - char tempBuffer[8192]; - std::string tempString; + va_list ap; + char tempBuffer[8192]; + std::string tempString; - va_start(ap, format ); - vsnprintf( tempBuffer, sizeof(tempBuffer), format , ap ); - va_end(ap); + va_start(ap, format ); + vsnprintf( tempBuffer, sizeof(tempBuffer), format , ap ); + va_end(ap); - tempString = tempBuffer; + tempString = tempBuffer; - return( tempString ); + return( tempString ); } const std::string stringtf( const std::string &format, ... ) { - va_list ap; - char tempBuffer[8192]; - std::string tempString; + va_list ap; + char tempBuffer[8192]; + std::string tempString; - va_start(ap, format ); - vsnprintf( tempBuffer, sizeof(tempBuffer), format.c_str() , ap ); - va_end(ap); + va_start(ap, format ); + vsnprintf( tempBuffer, sizeof(tempBuffer), format.c_str() , ap ); + va_end(ap); - tempString = tempBuffer; + tempString = tempBuffer; - return( tempString ); + return( tempString ); } bool startsWith( const std::string &haystack, const std::string &needle ) { - return( haystack.substr( 0, needle.length() ) == needle ); + return( haystack.substr( 0, needle.length() ) == needle ); } StringVector split( const std::string &string, const std::string chars, int limit ) { - StringVector stringVector; - std::string tempString = string; - std::string::size_type startIndex = 0; - std::string::size_type endIndex = 0; + StringVector stringVector; + std::string tempString = string; + std::string::size_type startIndex = 0; + std::string::size_type endIndex = 0; - //Info( "Looking for '%s' in '%s', limit %d", chars.c_str(), string.c_str(), limit ); - do + //Info( "Looking for '%s' in '%s', limit %d", chars.c_str(), string.c_str(), limit ); + do + { + // Find delimiters + endIndex = string.find_first_of( chars, startIndex ); + //Info( "Got endIndex at %d", endIndex ); + if ( endIndex > 0 ) { - // Find delimiters - endIndex = string.find_first_of( chars, startIndex ); - //Info( "Got endIndex at %d", endIndex ); - if ( endIndex > 0 ) - { - //Info( "Adding '%s'", string.substr( startIndex, endIndex-startIndex ).c_str() ); - stringVector.push_back( string.substr( startIndex, endIndex-startIndex ) ); - } - if ( endIndex == std::string::npos ) - break; - // Find non-delimiters - startIndex = tempString.find_first_not_of( chars, endIndex ); - if ( limit && (stringVector.size() == (unsigned int)(limit-1)) ) - { - stringVector.push_back( string.substr( startIndex ) ); - break; - } - //Info( "Got new startIndex at %d", startIndex ); - } while ( startIndex != std::string::npos ); - //Info( "Finished with %d strings", stringVector.size() ); + //Info( "Adding '%s'", string.substr( startIndex, endIndex-startIndex ).c_str() ); + stringVector.push_back( string.substr( startIndex, endIndex-startIndex ) ); + } + if ( endIndex == std::string::npos ) + break; + // Find non-delimiters + startIndex = tempString.find_first_not_of( chars, endIndex ); + if ( limit && (stringVector.size() == (unsigned int)(limit-1)) ) + { + stringVector.push_back( string.substr( startIndex ) ); + break; + } + //Info( "Got new startIndex at %d", startIndex ); + } while ( startIndex != std::string::npos ); + //Info( "Finished with %d strings", stringVector.size() ); - return( stringVector ); + return( stringVector ); } const std::string join(const StringVector v, const char * delim ) { - std::stringstream ss; + std::stringstream ss; - for(size_t i = 0; i < v.size(); ++i) { - if(i != 0) - ss << ","; - ss << v[i]; - } - return ss.str(); + for(size_t i = 0; i < v.size(); ++i) { + if(i != 0) + ss << ","; + ss << v[i]; + } + return ss.str(); } const std::string base64Encode( const std::string &inString ) { - static char base64_table[64] = { '\0' }; + static char base64_table[64] = { '\0' }; - if ( !base64_table[0] ) - { - int i = 0; - for ( char c = 'A'; c <= 'Z'; c++ ) - base64_table[i++] = c; - for ( char c = 'a'; c <= 'z'; c++ ) - base64_table[i++] = c; - for ( char c = '0'; c <= '9'; c++ ) - base64_table[i++] = c; - base64_table[i++] = '+'; - base64_table[i++] = '/'; - } + if ( !base64_table[0] ) + { + int i = 0; + for ( char c = 'A'; c <= 'Z'; c++ ) + base64_table[i++] = c; + for ( char c = 'a'; c <= 'z'; c++ ) + base64_table[i++] = c; + for ( char c = '0'; c <= '9'; c++ ) + base64_table[i++] = c; + base64_table[i++] = '+'; + base64_table[i++] = '/'; + } - std::string outString; - outString.reserve( 2 * inString.size() ); + std::string outString; + outString.reserve( 2 * inString.size() ); - const char *inPtr = inString.c_str(); - while( *inPtr ) - { - unsigned char selection = *inPtr >> 2; - unsigned char remainder = (*inPtr++ & 0x03) << 4; - outString += base64_table[selection]; + const char *inPtr = inString.c_str(); + while( *inPtr ) + { + unsigned char selection = *inPtr >> 2; + unsigned char remainder = (*inPtr++ & 0x03) << 4; + outString += base64_table[selection]; - if ( *inPtr ) - { - selection = remainder | (*inPtr >> 4); - remainder = (*inPtr++ & 0x0f) << 2; - outString += base64_table[selection]; - - if ( *inPtr ) - { - selection = remainder | (*inPtr >> 6); - outString += base64_table[selection]; - selection = (*inPtr++ & 0x3f); - outString += base64_table[selection]; - } - else - { - outString += base64_table[remainder]; - outString += '='; - } - } - else - { - outString += base64_table[remainder]; - outString += '='; - outString += '='; - } - } - return( outString ); + if ( *inPtr ) + { + selection = remainder | (*inPtr >> 4); + remainder = (*inPtr++ & 0x0f) << 2; + outString += base64_table[selection]; + + if ( *inPtr ) + { + selection = remainder | (*inPtr >> 6); + outString += base64_table[selection]; + selection = (*inPtr++ & 0x3f); + outString += base64_table[selection]; + } + else + { + outString += base64_table[remainder]; + outString += '='; + } + } + else + { + outString += base64_table[remainder]; + outString += '='; + outString += '='; + } + } + return( outString ); } int split(const char* string, const char delim, std::vector& items) { - if(string == NULL) - return -1; + if(string == NULL) + return -1; - if(string[0] == 0) - return -2; + if(string[0] == 0) + return -2; - std::string str(string); - size_t pos; - - while(true) { - pos = str.find(delim); - items.push_back(str.substr(0, pos)); - str.erase(0, pos+1); + std::string str(string); + size_t pos; + + while(true) { + pos = str.find(delim); + items.push_back(str.substr(0, pos)); + str.erase(0, pos+1); - if(pos == std::string::npos) - break; - } + if(pos == std::string::npos) + break; + } - return items.size(); + return items.size(); } int pairsplit(const char* string, const char delim, std::string& name, std::string& value) { - if(string == NULL) - return -1; + if(string == NULL) + return -1; - if(string[0] == 0) - return -2; + if(string[0] == 0) + return -2; - std::string str(string); - size_t pos = str.find(delim); + std::string str(string); + size_t pos = str.find(delim); - if(pos == std::string::npos || pos == 0 || pos >= str.length()) - return -3; + if(pos == std::string::npos || pos == 0 || pos >= str.length()) + return -3; - name = str.substr(0, pos); - value = str.substr(pos+1, std::string::npos); + name = str.substr(0, pos); + value = str.substr(pos+1, std::string::npos); - return 0; + return 0; } /* Sets sse_version */ void ssedetect() { #if (defined(__i386__) || defined(__x86_64__)) - /* x86 or x86-64 processor */ - uint32_t r_edx, r_ecx; - - __asm__ __volatile__( + /* x86 or x86-64 processor */ + uint32_t r_edx, r_ecx; + + __asm__ __volatile__( #if defined(__i386__) - "pushl %%ebx;\n\t" + "pushl %%ebx;\n\t" #endif - "mov $0x1,%%eax\n\t" - "cpuid\n\t" + "mov $0x1,%%eax\n\t" + "cpuid\n\t" #if defined(__i386__) - "popl %%ebx;\n\t" + "popl %%ebx;\n\t" #endif - : "=d" (r_edx), "=c" (r_ecx) - : - : "%eax" + : "=d" (r_edx), "=c" (r_ecx) + : + : "%eax" #if !defined(__i386__) - , "%ebx" + , "%ebx" #endif - ); - - if (r_ecx & 0x00000200) { - sseversion = 35; /* SSSE3 */ - Debug(1,"Detected a x86\\x86-64 processor with SSSE3"); - } else if (r_ecx & 0x00000001) { - sseversion = 30; /* SSE3 */ - Debug(1,"Detected a x86\\x86-64 processor with SSE3"); - } else if (r_edx & 0x04000000) { - sseversion = 20; /* SSE2 */ - Debug(1,"Detected a x86\\x86-64 processor with SSE2"); - } else if (r_edx & 0x02000000) { - sseversion = 10; /* SSE */ - Debug(1,"Detected a x86\\x86-64 processor with SSE"); - } else { - sseversion = 0; - Debug(1,"Detected a x86\\x86-64 processor"); - } - + ); + + if (r_ecx & 0x00000200) { + sseversion = 35; /* SSSE3 */ + Debug(1,"Detected a x86\\x86-64 processor with SSSE3"); + } else if (r_ecx & 0x00000001) { + sseversion = 30; /* SSE3 */ + Debug(1,"Detected a x86\\x86-64 processor with SSE3"); + } else if (r_edx & 0x04000000) { + sseversion = 20; /* SSE2 */ + Debug(1,"Detected a x86\\x86-64 processor with SSE2"); + } else if (r_edx & 0x02000000) { + sseversion = 10; /* SSE */ + Debug(1,"Detected a x86\\x86-64 processor with SSE"); + } else { + sseversion = 0; + Debug(1,"Detected a x86\\x86-64 processor"); + } + #else - /* Non x86 or x86-64 processor, SSE2 is not available */ - Debug(1,"Detected a non x86\\x86-64 processor"); - sseversion = 0; + /* Non x86 or x86-64 processor, SSE2 is not available */ + Debug(1,"Detected a non x86\\x86-64 processor"); + sseversion = 0; #endif } @@ -288,60 +288,60 @@ __attribute__((noinline,__target__("sse2"))) #endif void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes) { #if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) - if(bytes > 128) { - unsigned int remainder = bytes % 128; - const uint8_t* lastsrc = (uint8_t*)src + (bytes - remainder); + if(bytes > 128) { + unsigned int remainder = bytes % 128; + const uint8_t* lastsrc = (uint8_t*)src + (bytes - remainder); - __asm__ __volatile__( - "sse2_copy_iter:\n\t" - "movdqa (%0),%%xmm0\n\t" - "movdqa 0x10(%0),%%xmm1\n\t" - "movdqa 0x20(%0),%%xmm2\n\t" - "movdqa 0x30(%0),%%xmm3\n\t" - "movdqa 0x40(%0),%%xmm4\n\t" - "movdqa 0x50(%0),%%xmm5\n\t" - "movdqa 0x60(%0),%%xmm6\n\t" - "movdqa 0x70(%0),%%xmm7\n\t" - "movntdq %%xmm0,(%1)\n\t" - "movntdq %%xmm1,0x10(%1)\n\t" - "movntdq %%xmm2,0x20(%1)\n\t" - "movntdq %%xmm3,0x30(%1)\n\t" - "movntdq %%xmm4,0x40(%1)\n\t" - "movntdq %%xmm5,0x50(%1)\n\t" - "movntdq %%xmm6,0x60(%1)\n\t" - "movntdq %%xmm7,0x70(%1)\n\t" - "add $0x80, %0\n\t" - "add $0x80, %1\n\t" - "cmp %2, %0\n\t" - "jb sse2_copy_iter\n\t" - "test %3, %3\n\t" - "jz sse2_copy_finish\n\t" - "cld\n\t" - "rep movsb\n\t" - "sse2_copy_finish:\n\t" - : - : "S" (src), "D" (dest), "r" (lastsrc), "c" (remainder) - : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" - ); + __asm__ __volatile__( + "sse2_copy_iter:\n\t" + "movdqa (%0),%%xmm0\n\t" + "movdqa 0x10(%0),%%xmm1\n\t" + "movdqa 0x20(%0),%%xmm2\n\t" + "movdqa 0x30(%0),%%xmm3\n\t" + "movdqa 0x40(%0),%%xmm4\n\t" + "movdqa 0x50(%0),%%xmm5\n\t" + "movdqa 0x60(%0),%%xmm6\n\t" + "movdqa 0x70(%0),%%xmm7\n\t" + "movntdq %%xmm0,(%1)\n\t" + "movntdq %%xmm1,0x10(%1)\n\t" + "movntdq %%xmm2,0x20(%1)\n\t" + "movntdq %%xmm3,0x30(%1)\n\t" + "movntdq %%xmm4,0x40(%1)\n\t" + "movntdq %%xmm5,0x50(%1)\n\t" + "movntdq %%xmm6,0x60(%1)\n\t" + "movntdq %%xmm7,0x70(%1)\n\t" + "add $0x80, %0\n\t" + "add $0x80, %1\n\t" + "cmp %2, %0\n\t" + "jb sse2_copy_iter\n\t" + "test %3, %3\n\t" + "jz sse2_copy_finish\n\t" + "cld\n\t" + "rep movsb\n\t" + "sse2_copy_finish:\n\t" + : + : "S" (src), "D" (dest), "r" (lastsrc), "c" (remainder) + : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + ); - } else { - /* Standard memcpy */ - __asm__ __volatile__("cld; rep movsb" :: "S"(src), "D"(dest), "c"(bytes) : "cc", "memory"); - } + } else { + /* Standard memcpy */ + __asm__ __volatile__("cld; rep movsb" :: "S"(src), "D"(dest), "c"(bytes) : "cc", "memory"); + } #else - /* Non x86\x86-64 platform, use memcpy */ - memcpy(dest,src,bytes); + /* Non x86\x86-64 platform, use memcpy */ + memcpy(dest,src,bytes); #endif - return dest; + return dest; } void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff) { - if (((end->tv_nsec)-(start->tv_nsec))<0) { - diff->tv_sec = end->tv_sec-start->tv_sec-1; - diff->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec; - } else { - diff->tv_sec = end->tv_sec-start->tv_sec; - diff->tv_nsec = end->tv_nsec-start->tv_nsec; - } + if (((end->tv_nsec)-(start->tv_nsec))<0) { + diff->tv_sec = end->tv_sec-start->tv_sec-1; + diff->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec; + } else { + diff->tv_sec = end->tv_sec-start->tv_sec; + diff->tv_nsec = end->tv_nsec-start->tv_nsec; + } } diff --git a/src/zm_utils.h b/src/zm_utils.h index 063c74b7d..a6cb2e150 100644 --- a/src/zm_utils.h +++ b/src/zm_utils.h @@ -46,12 +46,12 @@ int pairsplit(const char* string, const char delim, std::string& name, std::stri inline int max( int a, int b ) { - return( a>=b?a:b ); + return( a>=b?a:b ); } inline int min( int a, int b ) { - return( a<=b?a:b ); + return( a<=b?a:b ); } void ssedetect(); diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp index 290f39131..f3d1120bc 100644 --- a/src/zm_zone.cpp +++ b/src/zm_zone.cpp @@ -25,170 +25,170 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames, int p_extend_alarm_frames ) { - monitor = p_monitor; + monitor = p_monitor; - id = p_id; - label = new char[strlen(p_label)+1]; - strcpy( label, p_label ); - type = p_type; - polygon = p_polygon; - alarm_rgb = p_alarm_rgb; - check_method = p_check_method; - min_pixel_threshold = p_min_pixel_threshold; - max_pixel_threshold = p_max_pixel_threshold; - min_alarm_pixels = p_min_alarm_pixels; - max_alarm_pixels = p_max_alarm_pixels; - filter_box = p_filter_box; - min_filter_pixels = p_min_filter_pixels; - max_filter_pixels = p_max_filter_pixels; - min_blob_pixels = p_min_blob_pixels; - max_blob_pixels = p_max_blob_pixels; - min_blobs = p_min_blobs; - max_blobs = p_max_blobs; - overload_frames = p_overload_frames; - extend_alarm_frames = p_extend_alarm_frames; + id = p_id; + label = new char[strlen(p_label)+1]; + strcpy( label, p_label ); + type = p_type; + polygon = p_polygon; + alarm_rgb = p_alarm_rgb; + check_method = p_check_method; + min_pixel_threshold = p_min_pixel_threshold; + max_pixel_threshold = p_max_pixel_threshold; + min_alarm_pixels = p_min_alarm_pixels; + max_alarm_pixels = p_max_alarm_pixels; + filter_box = p_filter_box; + min_filter_pixels = p_min_filter_pixels; + max_filter_pixels = p_max_filter_pixels; + min_blob_pixels = p_min_blob_pixels; + max_blob_pixels = p_max_blob_pixels; + min_blobs = p_min_blobs; + max_blobs = p_max_blobs; + overload_frames = p_overload_frames; + extend_alarm_frames = p_extend_alarm_frames; - Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames ); + Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames ); - alarmed = false; - pixel_diff = 0; - alarm_pixels = 0; - alarm_filter_pixels = 0; - alarm_blob_pixels = 0; - alarm_blobs = 0; - min_blob_size = 0; - max_blob_size = 0; - image = 0; - score = 0; + alarmed = false; + pixel_diff = 0; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blob_pixels = 0; + alarm_blobs = 0; + min_blob_size = 0; + max_blob_size = 0; + image = 0; + score = 0; - overload_count = 0; - extend_alarm_count = 0; + overload_count = 0; + extend_alarm_count = 0; - pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE); - pg_image->Clear(); - pg_image->Fill( 0xff, polygon ); - pg_image->Outline( 0xff, polygon ); + pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE); + pg_image->Clear(); + pg_image->Fill( 0xff, polygon ); + pg_image->Outline( 0xff, polygon ); - ranges = new Range[monitor->Height()]; - for ( unsigned int y = 0; y < monitor->Height(); y++) - { - ranges[y].lo_x = -1; - ranges[y].hi_x = 0; - ranges[y].off_x = 0; - const uint8_t *ppoly = pg_image->Buffer( 0, y ); - for ( unsigned int x = 0; x < monitor->Width(); x++, ppoly++ ) - { - if ( *ppoly ) - { - if ( ranges[y].lo_x == -1 ) - { - ranges[y].lo_x = x; - } - if ( (unsigned int)ranges[y].hi_x < x ) - { - ranges[y].hi_x = x; - } - } - } - } - - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id); - } - pg_image->WriteJpeg( diag_path ); - } + ranges = new Range[monitor->Height()]; + for ( unsigned int y = 0; y < monitor->Height(); y++) + { + ranges[y].lo_x = -1; + ranges[y].hi_x = 0; + ranges[y].off_x = 0; + const uint8_t *ppoly = pg_image->Buffer( 0, y ); + for ( unsigned int x = 0; x < monitor->Width(); x++, ppoly++ ) + { + if ( *ppoly ) + { + if ( ranges[y].lo_x == -1 ) + { + ranges[y].lo_x = x; + } + if ( (unsigned int)ranges[y].hi_x < x ) + { + ranges[y].hi_x = x; + } + } + } + } + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id); + } + pg_image->WriteJpeg( diag_path ); + } } Zone::~Zone() { - delete[] label; - delete image; - delete pg_image; - delete[] ranges; + delete[] label; + delete image; + delete pg_image; + delete[] ranges; } void Zone::RecordStats( const Event *event ) { static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't insert event stats: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event stats: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } } //============================================================================= bool Zone::CheckOverloadCount() { - Info("Overloaded count: %d, Overloaded frames: %d", overload_count, overload_frames); - if ( overload_count ) - { - Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); - Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); - overload_count--; - return( false ); - } - return true; + Info("Overloaded count: %d, Overloaded frames: %d", overload_count, overload_frames); + if ( overload_count ) + { + Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + overload_count--; + return( false ); + } + return true; } void Zone::SetScore(unsigned int nScore) { - score = nScore; + score = nScore; } void Zone::SetAlarmImage(const Image* srcImage) { - delete image; - image = new Image(*srcImage); + delete image; + image = new Image(*srcImage); } int Zone::GetOverloadCount() { - return overload_count; + return overload_count; } void Zone::SetOverloadCount(int nOverCount) { - overload_count = nOverCount; + overload_count = nOverCount; } int Zone::GetOverloadFrames() { - return overload_frames; + return overload_frames; } int Zone::GetExtendAlarmCount() { - return extend_alarm_count; + return extend_alarm_count; } void Zone::SetExtendAlarmCount(int nExtendAlarmCount) { - extend_alarm_count = nExtendAlarmCount; + extend_alarm_count = nExtendAlarmCount; } int Zone::GetExtendAlarmFrames() { - return extend_alarm_frames; + return extend_alarm_frames; } bool Zone::CheckExtendAlarmCount() { - Info("ExtendAlarm count: %d, ExtendAlarm frames: %d", extend_alarm_count, extend_alarm_frames); - if ( extend_alarm_count ) - { - Debug( 3, "In extend mode, %d frames of %d remaining", extend_alarm_count, extend_alarm_frames ); - extend_alarm_count--; - return( true ); - } - return false; + Info("ExtendAlarm count: %d, ExtendAlarm frames: %d", extend_alarm_count, extend_alarm_frames); + if ( extend_alarm_count ) + { + Debug( 3, "In extend mode, %d frames of %d remaining", extend_alarm_count, extend_alarm_frames ); + extend_alarm_count--; + return( true ); + } + return false; } @@ -198,920 +198,920 @@ bool Zone::CheckExtendAlarmCount() bool Zone::CheckAlarms( const Image *delta_image ) { - ResetStats(); + ResetStats(); - if ( overload_count ) - { - Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); - Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); - overload_count--; - return( false ); - } + if ( overload_count ) + { + Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + overload_count--; + return( false ); + } - delete image; - // Get the difference image - Image *diff_image = image = new Image( *delta_image ); - int diff_width = diff_image->Width(); - uint8_t* diff_buff = (uint8_t*)diff_image->Buffer(); - uint8_t* pdiff; - const uint8_t* ppoly; + delete image; + // Get the difference image + Image *diff_image = image = new Image( *delta_image ); + int diff_width = diff_image->Width(); + uint8_t* diff_buff = (uint8_t*)diff_image->Buffer(); + uint8_t* pdiff; + const uint8_t* ppoly; - unsigned int pixel_diff_count = 0; + unsigned int pixel_diff_count = 0; - int alarm_lo_x = 0; - int alarm_hi_x = 0; - int alarm_lo_y = 0; - int alarm_hi_y = 0; + int alarm_lo_x = 0; + int alarm_hi_x = 0; + int alarm_lo_y = 0; + int alarm_hi_y = 0; - int alarm_mid_x = -1; - int alarm_mid_y = -1; - - unsigned int lo_y = polygon.LoY(); - unsigned int lo_x = polygon.LoX(); - unsigned int hi_x = polygon.HiX(); - unsigned int hi_y = polygon.HiY(); + int alarm_mid_x = -1; + int alarm_mid_y = -1; + + unsigned int lo_y = polygon.LoY(); + unsigned int lo_x = polygon.LoX(); + unsigned int hi_x = polygon.HiX(); + unsigned int hi_y = polygon.HiY(); - Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y ); - - - Debug( 5, "Checking for alarmed pixels" ); - /* if(config.cpu_extensions && sseversion >= 20) { - sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); - } else { - std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); - } */ - std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); - - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 ); - } - diff_image->WriteJpeg( diag_path ); - } - - if ( pixel_diff_count && alarm_pixels ) - pixel_diff = pixel_diff_count/alarm_pixels; - Debug( 5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff ); + Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y ); + + + Debug( 5, "Checking for alarmed pixels" ); + /* if(config.cpu_extensions && sseversion >= 20) { + sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + } else { + std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + } */ + std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 ); + } + diff_image->WriteJpeg( diag_path ); + } + + if ( pixel_diff_count && alarm_pixels ) + pixel_diff = pixel_diff_count/alarm_pixels; + Debug( 5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff ); - if( alarm_pixels ) { - if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) { - /* Not enough pixels alarmed */ - return (false); - } else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) { - /* Too many pixels alarmed */ - overload_count = overload_frames; - return (false); - } - } else { - /* No alarmed pixels */ - return (false); - } - - score = (100*alarm_pixels)/polygon.Area(); - if(score < 1) - score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ - Debug( 5, "Current score is %d", score ); - - if ( check_method >= FILTERED_PIXELS ) - { - int bx = filter_box.X(); - int by = filter_box.Y(); - int bx1 = bx-1; - int by1 = by-1; + if( alarm_pixels ) { + if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) { + /* Not enough pixels alarmed */ + return (false); + } else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No alarmed pixels */ + return (false); + } + + score = (100*alarm_pixels)/polygon.Area(); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + if ( check_method >= FILTERED_PIXELS ) + { + int bx = filter_box.X(); + int by = filter_box.Y(); + int bx1 = bx-1; + int by1 = by-1; - Debug( 5, "Checking for filtered pixels" ); - if ( bx > 1 || by > 1 ) - { - // Now remove any pixels smaller than our filter size - unsigned char *cpdiff; - int ldx, hdx, ldy, hdy; - bool block; - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - int lo_x = ranges[y].lo_x; - int hi_x = ranges[y].hi_x; + Debug( 5, "Checking for filtered pixels" ); + if ( bx > 1 || by > 1 ) + { + // Now remove any pixels smaller than our filter size + unsigned char *cpdiff; + int ldx, hdx, ldy, hdy; + bool block; + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + int lo_x = ranges[y].lo_x; + int hi_x = ranges[y].hi_x; - pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); + pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); - for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) - { - if ( *pdiff == WHITE ) - { - // Check participation in an X block - ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; - hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); - ldy = (y>=(lo_y+by1))?-by1:lo_y-y; - hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); - block = false; - for ( int dy = ldy; !block && dy <= hdy; dy++ ) - { - for ( int dx = ldx; !block && dx <= hdx; dx++ ) - { - block = true; - for ( int dy2 = 0; block && dy2 < by; dy2++ ) - { - for ( int dx2 = 0; block && dx2 < bx; dx2++ ) - { - cpdiff = diff_buff + (((y+dy+dy2)*diff_width) + (x+dx+dx2)); - if ( !*cpdiff ) - { - block = false; - } - } - } - } - } - if ( !block ) - { - *pdiff = BLACK; - continue; - } - alarm_filter_pixels++; - } - } - } - } - else - { - alarm_filter_pixels = alarm_pixels; - } - - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 ); - } - diff_image->WriteJpeg( diag_path ); - } - - Debug( 5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels ); - - if( alarm_filter_pixels ) { - if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) { - /* Not enough pixels alarmed */ - return (false); - } else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) { - /* Too many pixels alarmed */ - overload_count = overload_frames; - return (false); - } - } else { - /* No filtered pixels */ - return (false); - } - - score = (100*alarm_filter_pixels)/(polygon.Area()); - if(score < 1) - score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ - Debug( 5, "Current score is %d", score ); + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + // Check participation in an X block + ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; + hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); + ldy = (y>=(lo_y+by1))?-by1:lo_y-y; + hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); + block = false; + for ( int dy = ldy; !block && dy <= hdy; dy++ ) + { + for ( int dx = ldx; !block && dx <= hdx; dx++ ) + { + block = true; + for ( int dy2 = 0; block && dy2 < by; dy2++ ) + { + for ( int dx2 = 0; block && dx2 < bx; dx2++ ) + { + cpdiff = diff_buff + (((y+dy+dy2)*diff_width) + (x+dx+dx2)); + if ( !*cpdiff ) + { + block = false; + } + } + } + } + } + if ( !block ) + { + *pdiff = BLACK; + continue; + } + alarm_filter_pixels++; + } + } + } + } + else + { + alarm_filter_pixels = alarm_pixels; + } + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 ); + } + diff_image->WriteJpeg( diag_path ); + } + + Debug( 5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels ); + + if( alarm_filter_pixels ) { + if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) { + /* Not enough pixels alarmed */ + return (false); + } else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No filtered pixels */ + return (false); + } + + score = (100*alarm_filter_pixels)/(polygon.Area()); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); - if ( check_method >= BLOBS ) - { - Debug( 5, "Checking for blob pixels" ); - typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; - BlobStats blob_stats[256]; - memset( blob_stats, 0, sizeof(BlobStats)*256 ); - uint8_t *spdiff; - uint8_t last_x, last_y; - BlobStats *bsx, *bsy; - BlobStats *bsm, *bss; - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - int lo_x = ranges[y].lo_x; - int hi_x = ranges[y].hi_x; + if ( check_method >= BLOBS ) + { + Debug( 5, "Checking for blob pixels" ); + typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; + BlobStats blob_stats[256]; + memset( blob_stats, 0, sizeof(BlobStats)*256 ); + uint8_t *spdiff; + uint8_t last_x, last_y; + BlobStats *bsx, *bsy; + BlobStats *bsm, *bss; + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + int lo_x = ranges[y].lo_x; + int hi_x = ranges[y].hi_x; - pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); - for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) - { - if ( *pdiff == WHITE ) - { - Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff ); - //last_x = (x>lo_x)?*(pdiff-1):0; - //last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0; - - last_x = 0; - if(x > 0) { - if((x-1) >= lo_x) { - last_x = *(pdiff-1); - } - } - - last_y = 0; - if(y > 0) { - if((y-1) >= lo_y && ranges[(y-1)].lo_x <= x && ranges[(y-1)].hi_x >= x) { - last_y = *(pdiff-diff_width); - } - } - - if ( last_x ) - { - Debug( 9, "Left neighbour is %d", last_x ); - bsx = &blob_stats[last_x]; - if ( last_y ) - { - Debug( 9, "Top neighbour is %d", last_y ); - bsy = &blob_stats[last_y]; - if ( last_x == last_y ) - { - Debug( 9, "Matching neighbours, setting to %d", last_x ); - // Add to the blob from the x side (either side really) - *pdiff = last_x; - alarm_blob_pixels++; - bsx->count++; - if ( x > bsx->hi_x ) bsx->hi_x = x; - if ( (int)y > bsx->hi_y ) bsx->hi_y = y; - } - else - { - // Aggregate blobs - bsm = bsx->count>=bsy->count?bsx:bsy; - bss = bsm==bsx?bsy:bsx; - - Debug( 9, "Different neighbours, setting pixels of %d to %d", bss->tag, bsm->tag ); - Debug( 9, "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); - Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); - // Now change all those pixels to the other setting - int changed = 0; - for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) - { - int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x; - int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x; - - Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx ); - Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x ); - spdiff = diff_buff + ((diff_width * sy) + lo_sx); - for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) - { - Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff ); - if ( *spdiff == bss->tag ) - { - Debug( 9, "Setting pixel" ); - *spdiff = bsm->tag; - changed++; - } - } - } - *pdiff = bsm->tag; - alarm_blob_pixels++; - if ( !changed ) - { - Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); - Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); - Error( "No pixels changed, exiting" ); - exit( -1 ); - } - - // Merge the slave blob into the master - bsm->count += bss->count+1; - if ( x > bsm->hi_x ) bsm->hi_x = x; - if ( (int)y > bsm->hi_y ) bsm->hi_y = y; - if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x; - if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y; - if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x; - if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y; - - alarm_blobs--; - - Debug( 6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs ); - - // Clear out the old blob - bss->tag = 0; - bss->count = 0; - bss->lo_x = 0; - bss->lo_y = 0; - bss->hi_x = 0; - bss->hi_y = 0; - } - } - else - { - Debug( 9, "Setting to left neighbour %d", last_x ); - // Add to the blob from the x side - *pdiff = last_x; - alarm_blob_pixels++; - bsx->count++; - if ( x > bsx->hi_x ) bsx->hi_x = x; - if ( (int)y > bsx->hi_y ) bsx->hi_y = y; - } - } - else - { - if ( last_y ) - { - Debug( 9, "Top neighbour is %d", last_y ); - Debug( 9, "Setting to top neighbour %d", last_y ); - - // Add to the blob from the y side - BlobStats *bsy = &blob_stats[last_y]; - - *pdiff = last_y; - alarm_blob_pixels++; - bsy->count++; - if ( x > bsy->hi_x ) bsy->hi_x = x; - if ( (int)y > bsy->hi_y ) bsy->hi_y = y; - } - else - { - // Create a new blob - int i; - for ( i = (WHITE-1); i > 0; i-- ) - { - BlobStats *bs = &blob_stats[i]; - // See if we can recycle one first, only if it's at least two rows up - if ( bs->count && bs->hi_y < (int)(y-1) ) - { - if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) - { - if ( config.create_analysis_images || config.record_diag_images ) - { - for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) - { - spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); - for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) - { - if ( *spdiff == bs->tag ) - { - *spdiff = BLACK; - } - } - } - } - alarm_blobs--; - alarm_blob_pixels -= bs->count; - - Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); - - bs->tag = 0; - bs->count = 0; - bs->lo_x = 0; - bs->lo_y = 0; - bs->hi_x = 0; - bs->hi_y = 0; - } - } - if ( !bs->count ) - { - Debug( 9, "Creating new blob %d", i ); - *pdiff = i; - alarm_blob_pixels++; - bs->tag = i; - bs->count++; - bs->lo_x = bs->hi_x = x; - bs->lo_y = bs->hi_y = y; - alarm_blobs++; - - Debug( 6, "Created blob %d at %d,%d, %d current blobs", bs->tag, x, y, alarm_blobs ); - break; - } - } - if ( i == 0 ) - { - Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." ); - x = hi_x+1; - y = hi_y+1; - } - } - } - } - } - } - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 ); - } - diff_image->WriteJpeg( diag_path ); - } - - if ( !alarm_blobs ) - { - return( false ); - } - - Debug( 5, "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); - - // Now eliminate blobs under the threshold - for ( int i = 1; i < WHITE; i++ ) - { - BlobStats *bs = &blob_stats[i]; - if ( bs->count ) - { - if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) - { - if ( config.create_analysis_images || config.record_diag_images ) - { - for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) - { - spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); - for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) - { - if ( *spdiff == bs->tag ) - { - *spdiff = BLACK; - } - } - } - } - alarm_blobs--; - alarm_blob_pixels -= bs->count; - - Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); - - bs->tag = 0; - bs->count = 0; - bs->lo_x = 0; - bs->lo_y = 0; - bs->hi_x = 0; - bs->hi_y = 0; - } - else - { - Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); - if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count; - if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count; - } - } - } - if ( config.record_diag_images ) - { - static char diag_path[PATH_MAX] = ""; - if ( !diag_path[0] ) - { - snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 ); - } - diff_image->WriteJpeg( diag_path ); - } - Debug( 5, "Got %d blob pixels, %d blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); + pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff ); + //last_x = (x>lo_x)?*(pdiff-1):0; + //last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0; - if( alarm_blobs ) { - if( min_blobs && (alarm_blobs < min_blobs) ) { - /* Not enough pixels alarmed */ - return (false); - } else if(max_blobs && (alarm_blobs > max_blobs) ) { - /* Too many pixels alarmed */ - overload_count = overload_frames; - return (false); - } - } else { - /* No blobs */ - return (false); - } - - score = (100*alarm_blob_pixels)/(polygon.Area()); - if(score < 1) - score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ - Debug( 5, "Current score is %d", score ); + last_x = 0; + if(x > 0) { + if((x-1) >= lo_x) { + last_x = *(pdiff-1); + } + } + + last_y = 0; + if(y > 0) { + if((y-1) >= lo_y && ranges[(y-1)].lo_x <= x && ranges[(y-1)].hi_x >= x) { + last_y = *(pdiff-diff_width); + } + } + + if ( last_x ) + { + Debug( 9, "Left neighbour is %d", last_x ); + bsx = &blob_stats[last_x]; + if ( last_y ) + { + Debug( 9, "Top neighbour is %d", last_y ); + bsy = &blob_stats[last_y]; + if ( last_x == last_y ) + { + Debug( 9, "Matching neighbours, setting to %d", last_x ); + // Add to the blob from the x side (either side really) + *pdiff = last_x; + alarm_blob_pixels++; + bsx->count++; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( (int)y > bsx->hi_y ) bsx->hi_y = y; + } + else + { + // Aggregate blobs + bsm = bsx->count>=bsy->count?bsx:bsy; + bss = bsm==bsx?bsy:bsx; - alarm_lo_x = polygon.HiX()+1; - alarm_hi_x = polygon.LoX()-1; - alarm_lo_y = polygon.HiY()+1; - alarm_hi_y = polygon.LoY()-1; - for ( int i = 1; i < WHITE; i++ ) - { - BlobStats *bs = &blob_stats[i]; - if ( bs->count ) - { - if ( bs->count == max_blob_size ) - { - if ( config.weighted_alarm_centres ) - { - unsigned long x_total = 0; - unsigned long y_total = 0; + Debug( 9, "Different neighbours, setting pixels of %d to %d", bss->tag, bsm->tag ); + Debug( 9, "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); + Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); + // Now change all those pixels to the other setting + int changed = 0; + for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) + { + int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x; + int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x; - for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) - { - spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); - for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) - { - if ( *spdiff == bs->tag ) - { - x_total += sx; - y_total += sy; - } - } - } - alarm_mid_x = int(round(x_total/bs->count)); - alarm_mid_y = int(round(y_total/bs->count)); - } - else - { - alarm_mid_x = int((bs->hi_x+bs->lo_x+1)/2); - alarm_mid_y = int((bs->hi_y+bs->lo_y+1)/2); - } - } + Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx ); + Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x ); + spdiff = diff_buff + ((diff_width * sy) + lo_sx); + for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) + { + Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff ); + if ( *spdiff == bss->tag ) + { + Debug( 9, "Setting pixel" ); + *spdiff = bsm->tag; + changed++; + } + } + } + *pdiff = bsm->tag; + alarm_blob_pixels++; + if ( !changed ) + { + Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); + Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); + Error( "No pixels changed, exiting" ); + exit( -1 ); + } - if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x; - if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y; - if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x; - if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; - } - } - } - else - { - alarm_mid_x = int((alarm_hi_x+alarm_lo_x+1)/2); - alarm_mid_y = int((alarm_hi_y+alarm_lo_y+1)/2); - } - } + // Merge the slave blob into the master + bsm->count += bss->count+1; + if ( x > bsm->hi_x ) bsm->hi_x = x; + if ( (int)y > bsm->hi_y ) bsm->hi_y = y; + if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x; + if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y; + if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x; + if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y; - if ( type == INCLUSIVE ) - { - // score >>= 1; - score /= 2; - } - else if ( type == EXCLUSIVE ) - { - // score <<= 1; - score *= 2; - - } + alarm_blobs--; - Debug( 5, "Adjusted score is %d", score ); + Debug( 6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs ); - // Now outline the changed region - if ( score ) - { - alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); + // Clear out the old blob + bss->tag = 0; + bss->count = 0; + bss->lo_x = 0; + bss->lo_y = 0; + bss->hi_x = 0; + bss->hi_y = 0; + } + } + else + { + Debug( 9, "Setting to left neighbour %d", last_x ); + // Add to the blob from the x side + *pdiff = last_x; + alarm_blob_pixels++; + bsx->count++; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( (int)y > bsx->hi_y ) bsx->hi_y = y; + } + } + else + { + if ( last_y ) + { + Debug( 9, "Top neighbour is %d", last_y ); + Debug( 9, "Setting to top neighbour %d", last_y ); + + // Add to the blob from the y side + BlobStats *bsy = &blob_stats[last_y]; - //if ( monitor->followMotion() ) - if ( true ) - { - alarm_centre = Coord( alarm_mid_x, alarm_mid_y ); - } - else - { - alarm_centre = alarm_box.Centre(); - } + *pdiff = last_y; + alarm_blob_pixels++; + bsy->count++; + if ( x > bsy->hi_x ) bsy->hi_x = x; + if ( (int)y > bsy->hi_y ) bsy->hi_y = y; + } + else + { + // Create a new blob + int i; + for ( i = (WHITE-1); i > 0; i-- ) + { + BlobStats *bs = &blob_stats[i]; + // See if we can recycle one first, only if it's at least two rows up + if ( bs->count && bs->hi_y < (int)(y-1) ) + { + if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) + { + if ( config.create_analysis_images || config.record_diag_images ) + { + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + } + alarm_blobs--; + alarm_blob_pixels -= bs->count; + + Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); - if ( (type < PRECLUSIVE) && check_method >= BLOBS && config.create_analysis_images ) - { + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + } + if ( !bs->count ) + { + Debug( 9, "Creating new blob %d", i ); + *pdiff = i; + alarm_blob_pixels++; + bs->tag = i; + bs->count++; + bs->lo_x = bs->hi_x = x; + bs->lo_y = bs->hi_y = y; + alarm_blobs++; - // First mask out anything we don't want - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - pdiff = diff_buff + ((diff_width * y) + lo_x); + Debug( 6, "Created blob %d at %d,%d, %d current blobs", bs->tag, x, y, alarm_blobs ); + break; + } + } + if ( i == 0 ) + { + Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." ); + x = hi_x+1; + y = hi_y+1; + } + } + } + } + } + } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 ); + } + diff_image->WriteJpeg( diag_path ); + } - int lo_x2 = ranges[y].lo_x; - int hi_x2 = ranges[y].hi_x; + if ( !alarm_blobs ) + { + return( false ); + } + + Debug( 5, "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); - int lo_gap = lo_x2-lo_x; - if ( lo_gap > 0 ) - { - if ( lo_gap == 1 ) - { - *pdiff++ = BLACK; - } - else - { - memset( pdiff, BLACK, lo_gap ); - pdiff += lo_gap; - } - } + // Now eliminate blobs under the threshold + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) + { + if ( config.create_analysis_images || config.record_diag_images ) + { + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + } + alarm_blobs--; + alarm_blob_pixels -= bs->count; + + Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); - ppoly = pg_image->Buffer( lo_x2, y ); - for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) - { - if ( !*ppoly ) - { - *pdiff = BLACK; - } - } + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + else + { + Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count; + if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count; + } + } + } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 ); + } + diff_image->WriteJpeg( diag_path ); + } + Debug( 5, "Got %d blob pixels, %d blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); + + if( alarm_blobs ) { + if( min_blobs && (alarm_blobs < min_blobs) ) { + /* Not enough pixels alarmed */ + return (false); + } else if(max_blobs && (alarm_blobs > max_blobs) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No blobs */ + return (false); + } + + score = (100*alarm_blob_pixels)/(polygon.Area()); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); - int hi_gap = hi_x-hi_x2; - if ( hi_gap > 0 ) - { - if ( hi_gap == 1 ) - { - *pdiff = BLACK; - } - else - { - memset( pdiff, BLACK, hi_gap ); - } - } - } - - if( monitor->Colours() == ZM_COLOUR_GRAY8 ) { - image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() ); - } else { - image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() ); - } - - // Only need to delete this when 'image' becomes detached and points somewhere else - delete diff_image; - } - else - { - delete image; - image = 0; - } + alarm_lo_x = polygon.HiX()+1; + alarm_hi_x = polygon.LoX()-1; + alarm_lo_y = polygon.HiY()+1; + alarm_hi_y = polygon.LoY()-1; + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( bs->count == max_blob_size ) + { + if ( config.weighted_alarm_centres ) + { + unsigned long x_total = 0; + unsigned long y_total = 0; - Debug( 1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d", Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score ); - } - return( true ); + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + x_total += sx; + y_total += sy; + } + } + } + alarm_mid_x = int(round(x_total/bs->count)); + alarm_mid_y = int(round(y_total/bs->count)); + } + else + { + alarm_mid_x = int((bs->hi_x+bs->lo_x+1)/2); + alarm_mid_y = int((bs->hi_y+bs->lo_y+1)/2); + } + } + + if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x; + if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y; + if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x; + if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; + } + } + } + else + { + alarm_mid_x = int((alarm_hi_x+alarm_lo_x+1)/2); + alarm_mid_y = int((alarm_hi_y+alarm_lo_y+1)/2); + } + } + + if ( type == INCLUSIVE ) + { + // score >>= 1; + score /= 2; + } + else if ( type == EXCLUSIVE ) + { + // score <<= 1; + score *= 2; + + } + + Debug( 5, "Adjusted score is %d", score ); + + // Now outline the changed region + if ( score ) + { + alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); + + //if ( monitor->followMotion() ) + if ( true ) + { + alarm_centre = Coord( alarm_mid_x, alarm_mid_y ); + } + else + { + alarm_centre = alarm_box.Centre(); + } + + if ( (type < PRECLUSIVE) && check_method >= BLOBS && config.create_analysis_images ) + { + + // First mask out anything we don't want + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + pdiff = diff_buff + ((diff_width * y) + lo_x); + + int lo_x2 = ranges[y].lo_x; + int hi_x2 = ranges[y].hi_x; + + int lo_gap = lo_x2-lo_x; + if ( lo_gap > 0 ) + { + if ( lo_gap == 1 ) + { + *pdiff++ = BLACK; + } + else + { + memset( pdiff, BLACK, lo_gap ); + pdiff += lo_gap; + } + } + + ppoly = pg_image->Buffer( lo_x2, y ); + for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) + { + if ( !*ppoly ) + { + *pdiff = BLACK; + } + } + + int hi_gap = hi_x-hi_x2; + if ( hi_gap > 0 ) + { + if ( hi_gap == 1 ) + { + *pdiff = BLACK; + } + else + { + memset( pdiff, BLACK, hi_gap ); + } + } + } + + if( monitor->Colours() == ZM_COLOUR_GRAY8 ) { + image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() ); + } else { + image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() ); + } + + // Only need to delete this when 'image' becomes detached and points somewhere else + delete diff_image; + } + else + { + delete image; + image = 0; + } + + Debug( 1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d", Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score ); + } + return( true ); } bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) { - Debug( 3, "Parsing polygon string '%s'", poly_string ); + Debug( 3, "Parsing polygon string '%s'", poly_string ); - char *str_ptr = new char[strlen(poly_string)+1]; - char *str = str_ptr; - strcpy( str, poly_string ); + char *str_ptr = new char[strlen(poly_string)+1]; + char *str = str_ptr; + strcpy( str, poly_string ); - char *ws; - int n_coords = 0; - int max_n_coords = strlen(str)/4; - Coord *coords = new Coord[max_n_coords]; - while( true ) - { - if ( *str == '\0' ) - { - break; - } - ws = strchr( str, ' ' ); - if ( ws ) - { - *ws = '\0'; - } - char *cp = strchr( str, ',' ); - if ( !cp ) - { - Error( "Bogus coordinate %s found in polygon string", str ); - delete[] coords; - delete[] str_ptr; - return( false ); - } - else - { - *cp = '\0'; - char *xp = str; - char *yp = cp+1; + char *ws; + int n_coords = 0; + int max_n_coords = strlen(str)/4; + Coord *coords = new Coord[max_n_coords]; + while( true ) + { + if ( *str == '\0' ) + { + break; + } + ws = strchr( str, ' ' ); + if ( ws ) + { + *ws = '\0'; + } + char *cp = strchr( str, ',' ); + if ( !cp ) + { + Error( "Bogus coordinate %s found in polygon string", str ); + delete[] coords; + delete[] str_ptr; + return( false ); + } + else + { + *cp = '\0'; + char *xp = str; + char *yp = cp+1; - int x = atoi(xp); - int y = atoi(yp); + int x = atoi(xp); + int y = atoi(yp); - Debug( 3, "Got coordinate %d,%d from polygon string", x, y ); + Debug( 3, "Got coordinate %d,%d from polygon string", x, y ); #if 0 - if ( x < 0 ) - x = 0; - else if ( x >= width ) - x = width-1; - if ( y < 0 ) - y = 0; - else if ( y >= height ) - y = height-1; + if ( x < 0 ) + x = 0; + else if ( x >= width ) + x = width-1; + if ( y < 0 ) + y = 0; + else if ( y >= height ) + y = height-1; #endif - coords[n_coords++] = Coord( x, y ); - } - if ( ws ) - str = ws+1; - else - break; - } - polygon = Polygon( n_coords, coords ); + coords[n_coords++] = Coord( x, y ); + } + if ( ws ) + str = ws+1; + else + break; + } + polygon = Polygon( n_coords, coords ); - Debug( 3, "Successfully parsed polygon string" ); - //printf( "Area: %d\n", pg.Area() ); - //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); + Debug( 3, "Successfully parsed polygon string" ); + //printf( "Area: %d\n", pg.Area() ); + //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); - delete[] coords; - delete[] str_ptr; + delete[] coords; + delete[] str_ptr; - return( true ); + return( true ); } bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ) { - Debug( 3, "Parsing zone string '%s'", zone_string ); + Debug( 3, "Parsing zone string '%s'", zone_string ); - char *str_ptr = new char[strlen(zone_string)+1]; - char *str = str_ptr; - strcpy( str, zone_string ); + char *str_ptr = new char[strlen(zone_string)+1]; + char *str = str_ptr; + strcpy( str, zone_string ); - char *ws = strchr( str, ' ' ); - if ( !ws ) - { - Debug( 3, "No initial whitespace found in zone string '%s', finishing", str ); - } - zone_id = strtol( str, 0, 10 ); - Debug( 3, "Got zone %d from zone string", zone_id ); - if ( !ws ) - { - delete str_ptr; - return( true ); - } + char *ws = strchr( str, ' ' ); + if ( !ws ) + { + Debug( 3, "No initial whitespace found in zone string '%s', finishing", str ); + } + zone_id = strtol( str, 0, 10 ); + Debug( 3, "Got zone %d from zone string", zone_id ); + if ( !ws ) + { + delete str_ptr; + return( true ); + } - *ws = '\0'; - str = ws+1; + *ws = '\0'; + str = ws+1; - ws = strchr( str, ' ' ); - if ( !ws ) - { - Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string ); - } - colour = strtol( str, 0, 16 ); - Debug( 3, "Got colour %06x from zone string", colour ); - if ( !ws ) - { - delete str_ptr; - return( true ); - } - *ws = '\0'; - str = ws+1; + ws = strchr( str, ' ' ); + if ( !ws ) + { + Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string ); + } + colour = strtol( str, 0, 16 ); + Debug( 3, "Got colour %06x from zone string", colour ); + if ( !ws ) + { + delete str_ptr; + return( true ); + } + *ws = '\0'; + str = ws+1; - bool result = ParsePolygonString( str, polygon ); + bool result = ParsePolygonString( str, polygon ); - //printf( "Area: %d\n", pg.Area() ); - //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); + //printf( "Area: %d\n", pg.Area() ); + //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); - delete[] str_ptr; + delete[] str_ptr; - return( result ); + return( result ); } int Zone::Load( Monitor *monitor, Zone **&zones ) { - static char sql[ZM_SQL_MED_BUFSIZ]; - snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames,ExtendAlarmFrames from Zones where MonitorId = %d order by Type, Id", monitor->Id() ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames,ExtendAlarmFrames from Zones where MonitorId = %d order by Type, Id", monitor->Id() ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_zones = mysql_num_rows( result ); - Debug( 1, "Got %d zones for monitor %s", n_zones, monitor->Name() ); - delete[] zones; - zones = new Zone *[n_zones]; - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int col = 0; + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_zones = mysql_num_rows( result ); + Debug( 1, "Got %d zones for monitor %s", n_zones, monitor->Name() ); + delete[] zones; + zones = new Zone *[n_zones]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; - int Id = atoi(dbrow[col++]); - const char *Name = dbrow[col++]; - int Type = atoi(dbrow[col++]); - const char *Units = dbrow[col++]; - const char *Coords = dbrow[col++]; - int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++; - int CheckMethod = atoi(dbrow[col++]); - int MinPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; - int MaxPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; - int MinAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; - int MaxAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; - int FilterX = dbrow[col]?atoi(dbrow[col]):0; col++; - int FilterY = dbrow[col]?atoi(dbrow[col]):0; col++; - int MinFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; - int MaxFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; - int MinBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; - int MaxBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; - int MinBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; - int MaxBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; - int OverloadFrames = dbrow[col]?atoi(dbrow[col]):0; col++; - int ExtendAlarmFrames = dbrow[col]?atoi(dbrow[col]):0; col++; - - /* HTML colour code is actually BGR in memory, we want RGB */ - AlarmRGB = rgb_convert(AlarmRGB, ZM_SUBPIX_ORDER_BGR); + int Id = atoi(dbrow[col++]); + const char *Name = dbrow[col++]; + int Type = atoi(dbrow[col++]); + const char *Units = dbrow[col++]; + const char *Coords = dbrow[col++]; + int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++; + int CheckMethod = atoi(dbrow[col++]); + int MinPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int FilterX = dbrow[col]?atoi(dbrow[col]):0; col++; + int FilterY = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; + int OverloadFrames = dbrow[col]?atoi(dbrow[col]):0; col++; + int ExtendAlarmFrames = dbrow[col]?atoi(dbrow[col]):0; col++; + + /* HTML colour code is actually BGR in memory, we want RGB */ + AlarmRGB = rgb_convert(AlarmRGB, ZM_SUBPIX_ORDER_BGR); - Debug( 5, "Parsing polygon %s", Coords ); - Polygon polygon; - if ( !ParsePolygonString( Coords, polygon ) ) { - Error( "Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring", Coords, Id, Name, monitor->Name() ); - continue; + Debug( 5, "Parsing polygon %s", Coords ); + Polygon polygon; + if ( !ParsePolygonString( Coords, polygon ) ) { + Error( "Unable to parse polygon string '%s' for zone %d/%s for monitor %s, ignoring", Coords, Id, Name, monitor->Name() ); + continue; + } + + if ( polygon.LoX() < 0 || polygon.HiX() >= (int)monitor->Width() + || polygon.LoY() < 0 || polygon.HiY() >= (int)monitor->Height() ) { + Error( "Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), ignoring", Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() ); + continue; + } + + if ( false && !strcmp( Units, "Percent" ) ) + { + MinAlarmPixels = (MinAlarmPixels*polygon.Area())/100; + MaxAlarmPixels = (MaxAlarmPixels*polygon.Area())/100; + MinFilterPixels = (MinFilterPixels*polygon.Area())/100; + MaxFilterPixels = (MaxFilterPixels*polygon.Area())/100; + MinBlobPixels = (MinBlobPixels*polygon.Area())/100; + MaxBlobPixels = (MaxBlobPixels*polygon.Area())/100; + } + + if ( atoi(dbrow[2]) == Zone::INACTIVE ) + { + zones[i] = new Zone( monitor, Id, Name, polygon ); + } + else if ( atoi(dbrow[2]) == Zone::PRIVACY ) + { + zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon ); } - - if ( polygon.LoX() < 0 || polygon.HiX() >= (int)monitor->Width() - || polygon.LoY() < 0 || polygon.HiY() >= (int)monitor->Height() ) { - Error( "Zone %d/%s for monitor %s extends outside of image dimensions, (%d,%d), (%d,%d), ignoring", Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() ); - continue; - } - - if ( false && !strcmp( Units, "Percent" ) ) - { - MinAlarmPixels = (MinAlarmPixels*polygon.Area())/100; - MaxAlarmPixels = (MaxAlarmPixels*polygon.Area())/100; - MinFilterPixels = (MinFilterPixels*polygon.Area())/100; - MaxFilterPixels = (MaxFilterPixels*polygon.Area())/100; - MinBlobPixels = (MinBlobPixels*polygon.Area())/100; - MaxBlobPixels = (MaxBlobPixels*polygon.Area())/100; - } - - if ( atoi(dbrow[2]) == Zone::INACTIVE ) - { - zones[i] = new Zone( monitor, Id, Name, polygon ); - } - else if ( atoi(dbrow[2]) == Zone::PRIVACY ) - { - zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon ); - } - { - zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames, ExtendAlarmFrames ); - } - } - if ( mysql_errno( &dbconn ) ) - { - Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - // Yadda yadda - mysql_free_result( result ); - return( n_zones ); + { + zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames, ExtendAlarmFrames ); + } + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + return( n_zones ); } bool Zone::DumpSettings( char *output, bool /*verbose*/ ) { - output[0] = 0; + output[0] = 0; - sprintf( output+strlen(output), " Id : %d\n", id ); - sprintf( output+strlen(output), " Label : %s\n", label ); - sprintf( output+strlen(output), " Type: %d - %s\n", type, - type==ACTIVE?"Active":( - type==INCLUSIVE?"Inclusive":( - type==EXCLUSIVE?"Exclusive":( - type==PRECLUSIVE?"Preclusive":( - type==INACTIVE?"Inactive":( - type==PRIVACY?"Privacy":"Unknown" - )))))); - sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() ); - for ( int i = 0; i < polygon.getNumCoords(); i++ ) - { - sprintf( output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).X(), polygon.getCoord( i ).Y() ); - } - sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb ); - sprintf( output+strlen(output), " Check Method: %d - %s\n", check_method, - check_method==ALARMED_PIXELS?"Alarmed Pixels":( - check_method==FILTERED_PIXELS?"FilteredPixels":( - check_method==BLOBS?"Blobs":"Unknown" - ))); - sprintf( output+strlen(output), " Min Pixel Threshold : %d\n", min_pixel_threshold ); - sprintf( output+strlen(output), " Max Pixel Threshold : %d\n", max_pixel_threshold ); - sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels ); - sprintf( output+strlen(output), " Max Alarm Pixels : %d\n", max_alarm_pixels ); - sprintf( output+strlen(output), " Filter Box : %d,%d\n", filter_box.X(), filter_box.Y() ); - sprintf( output+strlen(output), " Min Filter Pixels : %d\n", min_filter_pixels ); - sprintf( output+strlen(output), " Max Filter Pixels : %d\n", max_filter_pixels ); - sprintf( output+strlen(output), " Min Blob Pixels : %d\n", min_blob_pixels ); - sprintf( output+strlen(output), " Max Blob Pixels : %d\n", max_blob_pixels ); - sprintf( output+strlen(output), " Min Blobs : %d\n", min_blobs ); - sprintf( output+strlen(output), " Max Blobs : %d\n", max_blobs ); - return( true ); + sprintf( output+strlen(output), " Id : %d\n", id ); + sprintf( output+strlen(output), " Label : %s\n", label ); + sprintf( output+strlen(output), " Type: %d - %s\n", type, + type==ACTIVE?"Active":( + type==INCLUSIVE?"Inclusive":( + type==EXCLUSIVE?"Exclusive":( + type==PRECLUSIVE?"Preclusive":( + type==INACTIVE?"Inactive":( + type==PRIVACY?"Privacy":"Unknown" + )))))); + sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() ); + for ( int i = 0; i < polygon.getNumCoords(); i++ ) + { + sprintf( output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).X(), polygon.getCoord( i ).Y() ); + } + sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb ); + sprintf( output+strlen(output), " Check Method: %d - %s\n", check_method, + check_method==ALARMED_PIXELS?"Alarmed Pixels":( + check_method==FILTERED_PIXELS?"FilteredPixels":( + check_method==BLOBS?"Blobs":"Unknown" + ))); + sprintf( output+strlen(output), " Min Pixel Threshold : %d\n", min_pixel_threshold ); + sprintf( output+strlen(output), " Max Pixel Threshold : %d\n", max_pixel_threshold ); + sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels ); + sprintf( output+strlen(output), " Max Alarm Pixels : %d\n", max_alarm_pixels ); + sprintf( output+strlen(output), " Filter Box : %d,%d\n", filter_box.X(), filter_box.Y() ); + sprintf( output+strlen(output), " Min Filter Pixels : %d\n", min_filter_pixels ); + sprintf( output+strlen(output), " Max Filter Pixels : %d\n", max_filter_pixels ); + sprintf( output+strlen(output), " Min Blob Pixels : %d\n", min_blob_pixels ); + sprintf( output+strlen(output), " Max Blob Pixels : %d\n", max_blob_pixels ); + sprintf( output+strlen(output), " Min Blobs : %d\n", min_blobs ); + sprintf( output+strlen(output), " Max Blobs : %d\n", max_blobs ); + return( true ); } void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum) { - uint32_t pixelsalarmed = 0; - uint32_t pixelsdifference = 0; - uint8_t *pdiff; - const uint8_t *ppoly; - uint8_t calc_max_pixel_threshold = 255; - unsigned int lo_y; - unsigned int hi_y; - unsigned int lo_x; - unsigned int hi_x; - - if(max_pixel_threshold) - calc_max_pixel_threshold = max_pixel_threshold; - - lo_y = polygon.LoY(); - hi_y = polygon.HiY(); - for ( unsigned int y = lo_y; y <= hi_y; y++ ) - { - lo_x = ranges[y].lo_x; - hi_x = ranges[y].hi_x; - - Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x ); - pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y ); - ppoly = ppoly_image->Buffer( lo_x, y ); - - for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) - { - if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) - { - pixelsalarmed++; - pixelsdifference += *pdiff; - *pdiff = WHITE; - } - else - { - *pdiff = BLACK; - } - } - } - - /* Store the results */ - *pixel_count = pixelsalarmed; - *pixel_sum = pixelsdifference; + uint32_t pixelsalarmed = 0; + uint32_t pixelsdifference = 0; + uint8_t *pdiff; + const uint8_t *ppoly; + uint8_t calc_max_pixel_threshold = 255; + unsigned int lo_y; + unsigned int hi_y; + unsigned int lo_x; + unsigned int hi_x; + + if(max_pixel_threshold) + calc_max_pixel_threshold = max_pixel_threshold; + + lo_y = polygon.LoY(); + hi_y = polygon.HiY(); + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + lo_x = ranges[y].lo_x; + hi_x = ranges[y].hi_x; + + Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x ); + pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y ); + ppoly = ppoly_image->Buffer( lo_x, y ); + + for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) + { + if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) + { + pixelsalarmed++; + pixelsdifference += *pdiff; + *pdiff = WHITE; + } + else + { + *pdiff = BLACK; + } + } + } + + /* Store the results */ + *pixel_count = pixelsalarmed; + *pixel_sum = pixelsdifference; Debug( 7, "STORED"); } diff --git a/src/zm_zone.h b/src/zm_zone.h index d40b52b75..9b8a63747 100644 --- a/src/zm_zone.h +++ b/src/zm_zone.h @@ -35,141 +35,141 @@ class Monitor; class Zone { protected: - struct Range - { - int lo_x; - int hi_x; - int off_x; - }; + struct Range + { + int lo_x; + int hi_x; + int off_x; + }; public: - typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE, PRIVACY } ZoneType; - typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod; + typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE, PRIVACY } ZoneType; + typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod; protected: - // Inputs - Monitor *monitor; + // Inputs + Monitor *monitor; - int id; - char *label; - ZoneType type; - Polygon polygon; - Rgb alarm_rgb; - CheckMethod check_method; + int id; + char *label; + ZoneType type; + Polygon polygon; + Rgb alarm_rgb; + CheckMethod check_method; - int min_pixel_threshold; - int max_pixel_threshold; + int min_pixel_threshold; + int max_pixel_threshold; - int min_alarm_pixels; - int max_alarm_pixels; + int min_alarm_pixels; + int max_alarm_pixels; - Coord filter_box; - int min_filter_pixels; - int max_filter_pixels; + Coord filter_box; + int min_filter_pixels; + int max_filter_pixels; - int min_blob_pixels; - int max_blob_pixels; - int min_blobs; - int max_blobs; + int min_blob_pixels; + int max_blob_pixels; + int min_blobs; + int max_blobs; - int overload_frames; - int extend_alarm_frames; + int overload_frames; + int extend_alarm_frames; - // Outputs/Statistics - bool alarmed; - int pixel_diff; - unsigned int alarm_pixels; - int alarm_filter_pixels; - int alarm_blob_pixels; - int alarm_blobs; - int min_blob_size; - int max_blob_size; - Box alarm_box; - Coord alarm_centre; - unsigned int score; - Image *pg_image; - Range *ranges; - Image *image; + // Outputs/Statistics + bool alarmed; + int pixel_diff; + unsigned int alarm_pixels; + int alarm_filter_pixels; + int alarm_blob_pixels; + int alarm_blobs; + int min_blob_size; + int max_blob_size; + Box alarm_box; + Coord alarm_centre; + unsigned int score; + Image *pg_image; + Range *ranges; + Image *image; - int overload_count; - int extend_alarm_count; + int overload_count; + int extend_alarm_count; protected: - void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames, int p_extend_alarm_frames ); - void std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum); - + void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames, int p_extend_alarm_frames ); + void std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum); + public: - Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0, int p_extend_alarm_frames=0 ) - { - Setup( p_monitor, p_id, p_label, p_type, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames, p_extend_alarm_frames ); - } - Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0, int p_extend_alarm_frames=0) - { - Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames, p_extend_alarm_frames ); - } - Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon ) - { - Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 ); - } - Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon ) - { - Setup( p_monitor, p_id, p_label, p_type, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 ); - } + Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0, int p_extend_alarm_frames=0 ) + { + Setup( p_monitor, p_id, p_label, p_type, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames, p_extend_alarm_frames ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0, int p_extend_alarm_frames=0) + { + Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames, p_extend_alarm_frames ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon ) + { + Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon ) + { + Setup( p_monitor, p_id, p_label, p_type, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0, 0 ); + } public: - ~Zone(); + ~Zone(); - inline int Id() const { return( id ); } - inline const char *Label() const { return( label ); } - inline ZoneType Type() const { return( type ); } - inline bool IsActive() const { return( type == ACTIVE ); } - inline bool IsInclusive() const { return( type == INCLUSIVE ); } - inline bool IsExclusive() const { return( type == EXCLUSIVE ); } - inline bool IsPreclusive() const { return( type == PRECLUSIVE ); } - inline bool IsInactive() const { return( type == INACTIVE ); } - inline bool IsPrivacy() const { return( type == PRIVACY ); } - inline const Image *AlarmImage() const { return( image ); } - inline const Polygon &GetPolygon() const { return( polygon ); } - inline bool Alarmed() const { return( alarmed ); } - inline void SetAlarm() { alarmed = true; } - inline void ClearAlarm() { alarmed = false; } - inline Coord GetAlarmCentre() const { return( alarm_centre ); } - inline unsigned int Score() const { return( score ); } + inline int Id() const { return( id ); } + inline const char *Label() const { return( label ); } + inline ZoneType Type() const { return( type ); } + inline bool IsActive() const { return( type == ACTIVE ); } + inline bool IsInclusive() const { return( type == INCLUSIVE ); } + inline bool IsExclusive() const { return( type == EXCLUSIVE ); } + inline bool IsPreclusive() const { return( type == PRECLUSIVE ); } + inline bool IsInactive() const { return( type == INACTIVE ); } + inline bool IsPrivacy() const { return( type == PRIVACY ); } + inline const Image *AlarmImage() const { return( image ); } + inline const Polygon &GetPolygon() const { return( polygon ); } + inline bool Alarmed() const { return( alarmed ); } + inline void SetAlarm() { alarmed = true; } + inline void ClearAlarm() { alarmed = false; } + inline Coord GetAlarmCentre() const { return( alarm_centre ); } + inline unsigned int Score() const { return( score ); } - inline void ResetStats() - { - alarmed = false; - pixel_diff = 0; - alarm_pixels = 0; - alarm_filter_pixels = 0; - alarm_blob_pixels = 0; - alarm_blobs = 0; - min_blob_size = 0; - max_blob_size = 0; - score = 0; - } - void RecordStats( const Event *event ); - bool CheckAlarms( const Image *delta_image ); - bool DumpSettings( char *output, bool verbose ); + inline void ResetStats() + { + alarmed = false; + pixel_diff = 0; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blob_pixels = 0; + alarm_blobs = 0; + min_blob_size = 0; + max_blob_size = 0; + score = 0; + } + void RecordStats( const Event *event ); + bool CheckAlarms( const Image *delta_image ); + bool DumpSettings( char *output, bool verbose ); - static bool ParsePolygonString( const char *polygon_string, Polygon &polygon ); - static bool ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ); - static int Load( Monitor *monitor, Zone **&zones ); - //================================================= - bool CheckOverloadCount(); - int GetOverloadCount(); - void SetOverloadCount(int nOverCount); - int GetOverloadFrames(); - //================================================= - bool CheckExtendAlarmCount(); - int GetExtendAlarmCount(); - void SetExtendAlarmCount(int nOverCount); - int GetExtendAlarmFrames(); - void SetScore(unsigned int nScore); - void SetAlarmImage(const Image* srcImage); + static bool ParsePolygonString( const char *polygon_string, Polygon &polygon ); + static bool ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ); + static int Load( Monitor *monitor, Zone **&zones ); + //================================================= + bool CheckOverloadCount(); + int GetOverloadCount(); + void SetOverloadCount(int nOverCount); + int GetOverloadFrames(); + //================================================= + bool CheckExtendAlarmCount(); + int GetExtendAlarmCount(); + void SetExtendAlarmCount(int nOverCount); + int GetExtendAlarmFrames(); + void SetScore(unsigned int nScore); + void SetAlarmImage(const Image* srcImage); - inline const Image *getPgImage() const { return( pg_image ); } - inline const Range *getRanges() const { return( ranges ); } + inline const Image *getPgImage() const { return( pg_image ); } + inline const Range *getRanges() const { return( ranges ); } }; diff --git a/src/zma.cpp b/src/zma.cpp index 2d22d713a..03ffe1726 100644 --- a/src/zma.cpp +++ b/src/zma.cpp @@ -41,9 +41,9 @@ behind. =head1 OPTIONS - -m, --monitor_id - ID of the monitor to analyse - -h, --help - Display usage information - -v, --version - Print the installed version of ZoneMinder + -m, --monitor_id - ID of the monitor to analyse + -h, --help - Display usage information + -v, --version - Print the installed version of ZoneMinder =cut @@ -59,146 +59,146 @@ behind. void Usage() { - fprintf( stderr, "zma -m \n" ); - fprintf( stderr, "Options:\n" ); - fprintf( stderr, " -m, --monitor : Specify which monitor to use\n" ); - fprintf( stderr, " -h, --help : This screen\n" ); - fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" ); - exit( 0 ); + fprintf( stderr, "zma -m \n" ); + fprintf( stderr, "Options:\n" ); + fprintf( stderr, " -m, --monitor : Specify which monitor to use\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" ); + exit( 0 ); } int main( int argc, char *argv[] ) { - self = argv[0]; + self = argv[0]; - srand( getpid() * time( 0 ) ); + srand( getpid() * time( 0 ) ); - int id = -1; + int id = -1; - static struct option long_options[] = { - {"monitor", 1, 0, 'm'}, - {"help", 0, 0, 'h'}, - {"version", 0, 0, 'v'}, - {0, 0, 0, 0} - }; + static struct option long_options[] = { + {"monitor", 1, 0, 'm'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {0, 0, 0, 0} + }; - while (1) - { - int option_index = 0; + while (1) + { + int option_index = 0; - int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index); - if (c == -1) - { - break; - } + int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index); + if (c == -1) + { + break; + } - switch (c) - { - case 'm': - id = atoi(optarg); - break; - case 'h': - case '?': - Usage(); - break; - case 'v': - std::cout << ZM_VERSION << "\n"; - exit(0); - default: - //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); - break; - } - } + switch (c) + { + case 'm': + id = atoi(optarg); + break; + case 'h': + case '?': + Usage(); + break; + case 'v': + std::cout << ZM_VERSION << "\n"; + exit(0); + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } - if (optind < argc) - { - fprintf( stderr, "Extraneous options, " ); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - Usage(); - } + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + Usage(); + } - if ( id < 0 ) - { - fprintf( stderr, "Bogus monitor %d\n", id ); - Usage(); - exit( 0 ); - } + if ( id < 0 ) + { + fprintf( stderr, "Bogus monitor %d\n", id ); + Usage(); + exit( 0 ); + } - char log_id_string[16]; - snprintf( log_id_string, sizeof(log_id_string), "zma_m%d", id ); + char log_id_string[16]; + snprintf( log_id_string, sizeof(log_id_string), "zma_m%d", id ); - zmLoadConfig(); + zmLoadConfig(); - logInit( log_id_string ); - - ssedetect(); + logInit( log_id_string ); + + ssedetect(); - Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS ); + Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS ); - if ( monitor ) - { - Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() ); + if ( monitor ) + { + Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() ); - if ( config.opt_frame_server ) - { - Event::OpenFrameSocket( monitor->Id() ); - } + if ( config.opt_frame_server ) + { + Event::OpenFrameSocket( monitor->Id() ); + } - zmSetDefaultHupHandler(); - zmSetDefaultTermHandler(); - zmSetDefaultDieHandler(); + zmSetDefaultHupHandler(); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); - sigset_t block_set; - sigemptyset( &block_set ); + sigset_t block_set; + sigemptyset( &block_set ); - useconds_t analysis_rate = monitor->GetAnalysisRate(); - unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay(); - time_t last_analysis_update_time, cur_time; - monitor->UpdateAdaptiveSkip(); - last_analysis_update_time = time( 0 ); + useconds_t analysis_rate = monitor->GetAnalysisRate(); + unsigned int analysis_update_delay = monitor->GetAnalysisUpdateDelay(); + time_t last_analysis_update_time, cur_time; + monitor->UpdateAdaptiveSkip(); + last_analysis_update_time = time( 0 ); - while( !zm_terminate ) - { - // Process the next image - sigprocmask( SIG_BLOCK, &block_set, 0 ); + while( !zm_terminate ) + { + // Process the next image + sigprocmask( SIG_BLOCK, &block_set, 0 ); - // Some periodic updates are required for variable capturing framerate - if ( analysis_update_delay ) - { - cur_time = time( 0 ); - if ( ( cur_time - last_analysis_update_time ) > analysis_update_delay ) - { - analysis_rate = monitor->GetAnalysisRate(); - monitor->UpdateAdaptiveSkip(); - last_analysis_update_time = cur_time; - } - } + // Some periodic updates are required for variable capturing framerate + if ( analysis_update_delay ) + { + cur_time = time( 0 ); + if ( ( cur_time - last_analysis_update_time ) > analysis_update_delay ) + { + analysis_rate = monitor->GetAnalysisRate(); + monitor->UpdateAdaptiveSkip(); + last_analysis_update_time = cur_time; + } + } - if ( !monitor->Analyse() ) - { - usleep( monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE ); - } - else if ( analysis_rate ) - { - usleep( analysis_rate ); - } + if ( !monitor->Analyse() ) + { + usleep( monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE ); + } + else if ( analysis_rate ) + { + usleep( analysis_rate ); + } - if ( zm_reload ) - { - monitor->Reload(); - zm_reload = false; - } - sigprocmask( SIG_UNBLOCK, &block_set, 0 ); - } - delete monitor; - } - else - { - fprintf( stderr, "Can't find monitor with id of %d\n", id ); - } - logTerm(); - zmDbClose(); - return( 0 ); + if ( zm_reload ) + { + monitor->Reload(); + zm_reload = false; + } + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + } + delete monitor; + } + else + { + fprintf( stderr, "Can't find monitor with id of %d\n", id ); + } + logTerm(); + zmDbClose(); + return( 0 ); } diff --git a/src/zmc.cpp b/src/zmc.cpp index 56417d044..42b6b7aff 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -44,12 +44,12 @@ possible, this should run at more or less constant speed. =head1 OPTIONS - -d, --device - For local cameras, device to access. e.g /dev/video0 etc + -d, --device - For local cameras, device to access. e.g /dev/video0 etc -r -H -P -p - For remote cameras - -f, --file - For local images, jpg file to access. - -m, --monitor_id - ID of the monitor to analyse - -h, --help - Display usage information - -v, --version - Print the installed version of ZoneMinder + -f, --file - For local images, jpg file to access. + -m, --monitor_id - ID of the monitor to analyse + -h, --help - Display usage information + -v, --version - Print the installed version of ZoneMinder =cut @@ -75,290 +75,290 @@ possible, this should run at more or less constant speed. void Usage() { - fprintf( stderr, "zmc -d or -r -H -P -p or -f or -m \n" ); + fprintf( stderr, "zmc -d or -r -H -P -p or -f or -m \n" ); - fprintf( stderr, "Options:\n" ); + fprintf( stderr, "Options:\n" ); #if defined(BSD) - fprintf( stderr, " -d, --device : For local cameras, device to access. E.g /dev/bktr0 etc\n" ); + fprintf( stderr, " -d, --device : For local cameras, device to access. E.g /dev/bktr0 etc\n" ); #else - fprintf( stderr, " -d, --device : For local cameras, device to access. E.g /dev/video0 etc\n" ); + fprintf( stderr, " -d, --device : For local cameras, device to access. E.g /dev/video0 etc\n" ); #endif - fprintf( stderr, " -r -H -P -p : For remote cameras\n" ); - fprintf( stderr, " -f, --file : For local images, jpg file to access.\n" ); - fprintf( stderr, " -m, --monitor : For sources associated with a single monitor\n" ); - fprintf( stderr, " -h, --help : This screen\n" ); - fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" ); - exit( 0 ); + fprintf( stderr, " -r -H -P -p : For remote cameras\n" ); + fprintf( stderr, " -f, --file : For local images, jpg file to access.\n" ); + fprintf( stderr, " -m, --monitor : For sources associated with a single monitor\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" ); + exit( 0 ); } int main( int argc, char *argv[] ) { - self = argv[0]; + self = argv[0]; - srand( getpid() * time( 0 ) ); + srand( getpid() * time( 0 ) ); - const char *device = ""; - const char *protocol = ""; - const char *host = ""; - const char *port = ""; - const char *path = ""; - const char *file = ""; - int monitor_id = -1; + const char *device = ""; + const char *protocol = ""; + const char *host = ""; + const char *port = ""; + const char *path = ""; + const char *file = ""; + int monitor_id = -1; - static struct option long_options[] = { - {"device", 1, 0, 'd'}, - {"protocol", 1, 0, 'r'}, - {"host", 1, 0, 'H'}, - {"port", 1, 0, 'P'}, - {"path", 1, 0, 'p'}, - {"file", 1, 0, 'f'}, - {"monitor", 1, 0, 'm'}, - {"help", 0, 0, 'h'}, - {"version", 0, 0, 'v'}, - {0, 0, 0, 0} - }; + static struct option long_options[] = { + {"device", 1, 0, 'd'}, + {"protocol", 1, 0, 'r'}, + {"host", 1, 0, 'H'}, + {"port", 1, 0, 'P'}, + {"path", 1, 0, 'p'}, + {"file", 1, 0, 'f'}, + {"monitor", 1, 0, 'm'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {0, 0, 0, 0} + }; - while (1) - { - int option_index = 0; + while (1) + { + int option_index = 0; - int c = getopt_long (argc, argv, "d:H:P:p:f:m:h:v", long_options, &option_index); - if (c == -1) - { - break; - } + int c = getopt_long (argc, argv, "d:H:P:p:f:m:h:v", long_options, &option_index); + if (c == -1) + { + break; + } - switch (c) - { - case 'd': - device = optarg; - break; - case 'H': - host = optarg; - break; - case 'P': - port = optarg; - break; - case 'p': - path = optarg; - break; - case 'f': - file = optarg; - break; - case 'm': - monitor_id = atoi(optarg); - break; - case 'h': - case '?': - Usage(); - break; - case 'v': - std::cout << ZM_VERSION << "\n"; - exit(0); - default: - //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); - break; - } - } + switch (c) + { + case 'd': + device = optarg; + break; + case 'H': + host = optarg; + break; + case 'P': + port = optarg; + break; + case 'p': + path = optarg; + break; + case 'f': + file = optarg; + break; + case 'm': + monitor_id = atoi(optarg); + break; + case 'h': + case '?': + Usage(); + break; + case 'v': + std::cout << ZM_VERSION << "\n"; + exit(0); + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } - if (optind < argc) - { - fprintf( stderr, "Extraneous options, " ); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - Usage(); - } + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + Usage(); + } - int modes = ( device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id>0?1:0) ); - if ( modes > 1 ) - { - fprintf( stderr, "Only one of device, host/port/path, file or monitor id allowed\n" ); - Usage(); - exit( 0 ); - } + int modes = ( device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id>0?1:0) ); + if ( modes > 1 ) + { + fprintf( stderr, "Only one of device, host/port/path, file or monitor id allowed\n" ); + Usage(); + exit( 0 ); + } - if ( modes < 1 ) - { - fprintf( stderr, "One of device, host/port/path, file or monitor id must be specified\n" ); - Usage(); - exit( 0 ); - } + if ( modes < 1 ) + { + fprintf( stderr, "One of device, host/port/path, file or monitor id must be specified\n" ); + Usage(); + exit( 0 ); + } - char log_id_string[32] = ""; - if ( device[0] ) - { - const char *slash_ptr = strrchr( device, '/' ); - snprintf( log_id_string, sizeof(log_id_string), "zmc_d%s", slash_ptr?slash_ptr+1:device ); - } - else if ( host[0] ) - { - snprintf( log_id_string, sizeof(log_id_string), "zmc_h%s", host ); - } - else if ( file[0] ) - { - const char *slash_ptr = strrchr( file, '/' ); - snprintf( log_id_string, sizeof(log_id_string), "zmc_f%s", slash_ptr?slash_ptr+1:file ); - } - else - { - snprintf( log_id_string, sizeof(log_id_string), "zmc_m%d", monitor_id ); - } + char log_id_string[32] = ""; + if ( device[0] ) + { + const char *slash_ptr = strrchr( device, '/' ); + snprintf( log_id_string, sizeof(log_id_string), "zmc_d%s", slash_ptr?slash_ptr+1:device ); + } + else if ( host[0] ) + { + snprintf( log_id_string, sizeof(log_id_string), "zmc_h%s", host ); + } + else if ( file[0] ) + { + const char *slash_ptr = strrchr( file, '/' ); + snprintf( log_id_string, sizeof(log_id_string), "zmc_f%s", slash_ptr?slash_ptr+1:file ); + } + else + { + snprintf( log_id_string, sizeof(log_id_string), "zmc_m%d", monitor_id ); + } - zmLoadConfig(); + zmLoadConfig(); - logInit( log_id_string ); - - ssedetect(); + logInit( log_id_string ); + + ssedetect(); - Monitor **monitors = 0; - int n_monitors = 0; + Monitor **monitors = 0; + int n_monitors = 0; #if ZM_HAS_V4L - if ( device[0] ) - { - n_monitors = Monitor::LoadLocalMonitors( device, monitors, Monitor::CAPTURE ); - } - else + if ( device[0] ) + { + n_monitors = Monitor::LoadLocalMonitors( device, monitors, Monitor::CAPTURE ); + } + else #endif // ZM_HAS_V4L - if ( host[0] ) - { - if ( !port ) - port = "80"; - n_monitors = Monitor::LoadRemoteMonitors( protocol, host, port, path, monitors, Monitor::CAPTURE ); - } - else if ( file[0] ) - { - n_monitors = Monitor::LoadFileMonitors( file, monitors, Monitor::CAPTURE ); - } - else - { - Monitor *monitor = Monitor::Load( monitor_id, true, Monitor::CAPTURE ); - if ( monitor ) - { - monitors = new Monitor *[1]; - monitors[0] = monitor; - n_monitors = 1; - } - } + if ( host[0] ) + { + if ( !port ) + port = "80"; + n_monitors = Monitor::LoadRemoteMonitors( protocol, host, port, path, monitors, Monitor::CAPTURE ); + } + else if ( file[0] ) + { + n_monitors = Monitor::LoadFileMonitors( file, monitors, Monitor::CAPTURE ); + } + else + { + Monitor *monitor = Monitor::Load( monitor_id, true, Monitor::CAPTURE ); + if ( monitor ) + { + monitors = new Monitor *[1]; + monitors[0] = monitor; + n_monitors = 1; + } + } - if ( !n_monitors ) - { - Error( "No monitors found" ); - exit ( -1 ); - } + if ( !n_monitors ) + { + Error( "No monitors found" ); + exit ( -1 ); + } - Info( "Starting Capture version %s", ZM_VERSION ); + Info( "Starting Capture version %s", ZM_VERSION ); - zmSetDefaultTermHandler(); - zmSetDefaultDieHandler(); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); - sigset_t block_set; - sigemptyset( &block_set ); + sigset_t block_set; + sigemptyset( &block_set ); - sigaddset( &block_set, SIGUSR1 ); - sigaddset( &block_set, SIGUSR2 ); + sigaddset( &block_set, SIGUSR1 ); + sigaddset( &block_set, SIGUSR2 ); - if ( monitors[0]->PrimeCapture() < 0 ) - { - Error( "Failed to prime capture of initial monitor" ); - exit( -1 ); - } + if ( monitors[0]->PrimeCapture() < 0 ) + { + Error( "Failed to prime capture of initial monitor" ); + exit( -1 ); + } - long *capture_delays = new long[n_monitors]; - long *alarm_capture_delays = new long[n_monitors]; - long *next_delays = new long[n_monitors]; - struct timeval * last_capture_times = new struct timeval[n_monitors]; - for ( int i = 0; i < n_monitors; i++ ) - { - last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0; - capture_delays[i] = monitors[i]->GetCaptureDelay(); - alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay(); - } + long *capture_delays = new long[n_monitors]; + long *alarm_capture_delays = new long[n_monitors]; + long *next_delays = new long[n_monitors]; + struct timeval * last_capture_times = new struct timeval[n_monitors]; + for ( int i = 0; i < n_monitors; i++ ) + { + last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0; + capture_delays[i] = monitors[i]->GetCaptureDelay(); + alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay(); + } - int result = 0; - struct timeval now; - struct DeltaTimeval delta_time; - while( !zm_terminate ) - { - sigprocmask( SIG_BLOCK, &block_set, 0 ); - for ( int i = 0; i < n_monitors; i++ ) - { - long min_delay = MAXINT; + int result = 0; + struct timeval now; + struct DeltaTimeval delta_time; + while( !zm_terminate ) + { + sigprocmask( SIG_BLOCK, &block_set, 0 ); + for ( int i = 0; i < n_monitors; i++ ) + { + long min_delay = MAXINT; - gettimeofday( &now, NULL ); - for ( int j = 0; j < n_monitors; j++ ) - { - if ( last_capture_times[j].tv_sec ) - { - DELTA_TIMEVAL( delta_time, now, last_capture_times[j], DT_PREC_3 ); - if ( monitors[i]->GetState() == Monitor::ALARM ) - next_delays[j] = alarm_capture_delays[j]-delta_time.delta; - else - next_delays[j] = capture_delays[j]-delta_time.delta; - if ( next_delays[j] < 0 ) - next_delays[j] = 0; - } - else - { - next_delays[j] = 0; - } - if ( next_delays[j] <= min_delay ) - { - min_delay = next_delays[j]; - } - } + gettimeofday( &now, NULL ); + for ( int j = 0; j < n_monitors; j++ ) + { + if ( last_capture_times[j].tv_sec ) + { + DELTA_TIMEVAL( delta_time, now, last_capture_times[j], DT_PREC_3 ); + if ( monitors[i]->GetState() == Monitor::ALARM ) + next_delays[j] = alarm_capture_delays[j]-delta_time.delta; + else + next_delays[j] = capture_delays[j]-delta_time.delta; + if ( next_delays[j] < 0 ) + next_delays[j] = 0; + } + else + { + next_delays[j] = 0; + } + if ( next_delays[j] <= min_delay ) + { + min_delay = next_delays[j]; + } + } - if ( next_delays[i] <= min_delay || next_delays[i] <= 0 ) - { - if ( monitors[i]->PreCapture() < 0 ) - { - Error( "Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors ); - zm_terminate = true; - result = -1; - break; - } - if ( monitors[i]->Capture() < 0 ) - { - Error( "Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors ); - zm_terminate = true; - result = -1; - break; - } - if ( monitors[i]->PostCapture() < 0 ) - { - Error( "Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors ); - zm_terminate = true; - result = -1; - break; - } + if ( next_delays[i] <= min_delay || next_delays[i] <= 0 ) + { + if ( monitors[i]->PreCapture() < 0 ) + { + Error( "Failed to pre-capture monitor %d %d (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors ); + zm_terminate = true; + result = -1; + break; + } + if ( monitors[i]->Capture() < 0 ) + { + Error( "Failed to capture image from monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors ); + zm_terminate = true; + result = -1; + break; + } + if ( monitors[i]->PostCapture() < 0 ) + { + Error( "Failed to post-capture monitor %d %s (%d/%d)", monitors[i]->Id(), monitors[i]->Name(), i+1, n_monitors ); + zm_terminate = true; + result = -1; + break; + } - if ( next_delays[i] > 0 ) - { - gettimeofday( &now, NULL ); - DELTA_TIMEVAL( delta_time, now, last_capture_times[i], DT_PREC_3 ); - long sleep_time = next_delays[i]-delta_time.delta; - if ( sleep_time > 0 ) - { - usleep( sleep_time*(DT_MAXGRAN/DT_PREC_3) ); - } - } - gettimeofday( &(last_capture_times[i]), NULL ); - } - } - sigprocmask( SIG_UNBLOCK, &block_set, 0 ); - } - for ( int i = 0; i < n_monitors; i++ ) - { - delete monitors[i]; - } - delete [] monitors; - delete [] alarm_capture_delays; - delete [] capture_delays; - delete [] next_delays; - delete [] last_capture_times; + if ( next_delays[i] > 0 ) + { + gettimeofday( &now, NULL ); + DELTA_TIMEVAL( delta_time, now, last_capture_times[i], DT_PREC_3 ); + long sleep_time = next_delays[i]-delta_time.delta; + if ( sleep_time > 0 ) + { + usleep( sleep_time*(DT_MAXGRAN/DT_PREC_3) ); + } + } + gettimeofday( &(last_capture_times[i]), NULL ); + } + } + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + } + for ( int i = 0; i < n_monitors; i++ ) + { + delete monitors[i]; + } + delete [] monitors; + delete [] alarm_capture_delays; + delete [] capture_delays; + delete [] next_delays; + delete [] last_capture_times; - logTerm(); - zmDbClose(); + logTerm(); + zmDbClose(); - return( result ); + return( result ); } diff --git a/src/zmf.cpp b/src/zmf.cpp index 7abe7a897..a739927f1 100644 --- a/src/zmf.cpp +++ b/src/zmf.cpp @@ -42,9 +42,9 @@ them itself. =head1 OPTIONS - -m, --monitor_id - ID of the monitor to use - -h, --help - Display usage information - -v, --version - Print the installed version of ZoneMinder + -m, --monitor_id - ID of the monitor to use + -h, --help - Display usage information + -v, --version - Print the installed version of ZoneMinder =cut @@ -73,278 +73,278 @@ them itself. int OpenSocket( int monitor_id ) { - int sd = socket( AF_UNIX, SOCK_STREAM, 0); - if ( sd < 0 ) - { - Error( "Can't create socket: %s", strerror(errno) ); - return( -1 ); - } + int sd = socket( AF_UNIX, SOCK_STREAM, 0); + if ( sd < 0 ) + { + Error( "Can't create socket: %s", strerror(errno) ); + return( -1 ); + } - char sock_path[PATH_MAX] = ""; - snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id ); - if ( unlink( sock_path ) < 0 ) - { - Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) ); - } + char sock_path[PATH_MAX] = ""; + snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id ); + if ( unlink( sock_path ) < 0 ) + { + Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) ); + } - struct sockaddr_un addr; + struct sockaddr_un addr; - strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) ); - addr.sun_family = AF_UNIX; + strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) ); + addr.sun_family = AF_UNIX; - if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 ) - { - Error( "Can't bind: %s", strerror(errno) ); - exit( -1 ); - } + if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 ) + { + Error( "Can't bind: %s", strerror(errno) ); + exit( -1 ); + } - if ( listen( sd, SOMAXCONN ) < 0 ) - { - Error( "Can't listen: %s", strerror(errno) ); - return( -1 ); - } + if ( listen( sd, SOMAXCONN ) < 0 ) + { + Error( "Can't listen: %s", strerror(errno) ); + return( -1 ); + } - struct sockaddr_un rem_addr; - socklen_t rem_addr_len = sizeof(rem_addr); - int new_sd = -1; - if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 ) - { - Error( "Can't accept: %s", strerror(errno) ); - exit( -1 ); - } - close( sd ); + struct sockaddr_un rem_addr; + socklen_t rem_addr_len = sizeof(rem_addr); + int new_sd = -1; + if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 ) + { + Error( "Can't accept: %s", strerror(errno) ); + exit( -1 ); + } + close( sd ); - sd = new_sd; + sd = new_sd; - Info( "Frame server socket open, awaiting images" ); - return( sd ); + Info( "Frame server socket open, awaiting images" ); + return( sd ); } int ReopenSocket( int &sd, int monitor_id ) { - close( sd ); - return( sd = OpenSocket( monitor_id ) ); + close( sd ); + return( sd = OpenSocket( monitor_id ) ); } void Usage() { - fprintf( stderr, "zmf -m \n" ); - fprintf( stderr, "Options:\n" ); - fprintf( stderr, " -m, --monitor : Specify which monitor to use\n" ); - fprintf( stderr, " -h, --help : This screen\n" ); - fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" ); - exit( 0 ); + fprintf( stderr, "zmf -m \n" ); + fprintf( stderr, "Options:\n" ); + fprintf( stderr, " -m, --monitor : Specify which monitor to use\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" ); + exit( 0 ); } int main( int argc, char *argv[] ) { - self = argv[0]; + self = argv[0]; - srand( getpid() * time( 0 ) ); + srand( getpid() * time( 0 ) ); - int id = -1; + int id = -1; - static struct option long_options[] = { - {"monitor", 1, 0, 'm'}, - {"help", 0, 0, 'h'}, - {"version", 0, 0, 'v'}, - {0, 0, 0, 0} - }; + static struct option long_options[] = { + {"monitor", 1, 0, 'm'}, + {"help", 0, 0, 'h'}, + {"version", 0, 0, 'v'}, + {0, 0, 0, 0} + }; - while (1) - { - int option_index = 0; + while (1) + { + int option_index = 0; - int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index); - if (c == -1) - { - break; - } + int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index); + if (c == -1) + { + break; + } - switch (c) - { - case 'm': - id = atoi(optarg); - break; - case 'h': - case '?': - Usage(); - break; - case 'v': - std::cout << ZM_VERSION << "\n"; - exit(0); - default: - //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); - break; - } - } + switch (c) + { + case 'm': + id = atoi(optarg); + break; + case 'h': + case '?': + Usage(); + break; + case 'v': + std::cout << ZM_VERSION << "\n"; + exit(0); + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } - if (optind < argc) - { - fprintf( stderr, "Extraneous options, " ); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - Usage(); - } + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + Usage(); + } - if ( id < 0 ) - { - fprintf( stderr, "Bogus monitor %d\n", id ); - Usage(); - exit( 0 ); - } + if ( id < 0 ) + { + fprintf( stderr, "Bogus monitor %d\n", id ); + Usage(); + exit( 0 ); + } - char log_id_string[16]; - snprintf( log_id_string, sizeof(log_id_string), "m%d", id ); + char log_id_string[16]; + snprintf( log_id_string, sizeof(log_id_string), "m%d", id ); - zmLoadConfig(); + zmLoadConfig(); - logInit( "zmf" ); - - ssedetect(); + logInit( "zmf" ); + + ssedetect(); - Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY ); + Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY ); - if ( !monitor ) - { - fprintf( stderr, "Can't find monitor with id of %d\n", id ); - exit( -1 ); - } + if ( !monitor ) + { + fprintf( stderr, "Can't find monitor with id of %d\n", id ); + exit( -1 ); + } - char capt_path[PATH_MAX]; - char anal_path[PATH_MAX]; - snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits ); - snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits ); - zmSetDefaultTermHandler(); - zmSetDefaultDieHandler(); + char capt_path[PATH_MAX]; + char anal_path[PATH_MAX]; + snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits ); + snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits ); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); - sigset_t block_set; - sigemptyset( &block_set ); + sigset_t block_set; + sigemptyset( &block_set ); - int sd = OpenSocket( monitor->Id() ); + int sd = OpenSocket( monitor->Id() ); - FrameHeader frame_header = { 0, 0, false, 0 }; - //unsigned char *image_data = 0; + FrameHeader frame_header = { 0, 0, false, 0 }; + //unsigned char *image_data = 0; - fd_set rfds; + fd_set rfds; - struct timeval timeout; - timeout.tv_sec = 1; - timeout.tv_usec = 0; - while( 1 ) - { - struct timeval temp_timeout = timeout; + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + while( 1 ) + { + struct timeval temp_timeout = timeout; - FD_ZERO(&rfds); - FD_SET(sd, &rfds); - int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout ); - if( n_found == 0 ) - { - Debug( 1, "Select timed out" ); - continue; - } - else if ( n_found < 0) - { - Error( "Select error: %s", strerror(errno) ); - ReopenSocket( sd, monitor->Id() ); - continue; - } + FD_ZERO(&rfds); + FD_SET(sd, &rfds); + int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout ); + if( n_found == 0 ) + { + Debug( 1, "Select timed out" ); + continue; + } + else if ( n_found < 0) + { + Error( "Select error: %s", strerror(errno) ); + ReopenSocket( sd, monitor->Id() ); + continue; + } - sigprocmask( SIG_BLOCK, &block_set, 0 ); + sigprocmask( SIG_BLOCK, &block_set, 0 ); - int n_bytes = read( sd, &frame_header, sizeof(frame_header) ); - if ( n_bytes != sizeof(frame_header) ) - { - if ( n_bytes < 0 ) - { - Error( "Can't read frame header: %s", strerror(errno) ); - } - else if ( n_bytes > 0 ) - { - Error( "Incomplete read of frame header, %d bytes only", n_bytes ); - } - else - { - Warning( "Socket closed at remote end" ); - } - ReopenSocket( sd, monitor->Id() ); - continue; - } - Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length ); - static unsigned char image_data[ZM_MAX_IMAGE_SIZE]; + int n_bytes = read( sd, &frame_header, sizeof(frame_header) ); + if ( n_bytes != sizeof(frame_header) ) + { + if ( n_bytes < 0 ) + { + Error( "Can't read frame header: %s", strerror(errno) ); + } + else if ( n_bytes > 0 ) + { + Error( "Incomplete read of frame header, %d bytes only", n_bytes ); + } + else + { + Warning( "Socket closed at remote end" ); + } + ReopenSocket( sd, monitor->Id() ); + continue; + } + Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length ); + static unsigned char image_data[ZM_MAX_IMAGE_SIZE]; - // Read for pipe and loop until bytes expected have been read or an error occurs - int bytes_read = 0; - do - { - n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read ); - if (n_bytes < 0) break; // break on error - if (n_bytes < (int)frame_header.image_length) - { - // print some informational messages - if (bytes_read == 0) - { - Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length); - } - else if (bytes_read+n_bytes == (int)frame_header.image_length) - { - Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length); - } - else - { - Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes); - } - } - bytes_read+= n_bytes; - } while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) ); - - // Print errors if there was a problem - if ( n_bytes < 1 ) + // Read for pipe and loop until bytes expected have been read or an error occurs + int bytes_read = 0; + do + { + n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read ); + if (n_bytes < 0) break; // break on error + if (n_bytes < (int)frame_header.image_length) + { + // print some informational messages + if (bytes_read == 0) { - Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length); - if ( n_bytes < 0 ) - { - Error( "Can't read frame image data: %s", strerror(errno) ); - } - else - { - Warning( "Socket closed at remote end" ); - } - ReopenSocket( sd, monitor->Id() ); - continue; - } - - static char subpath[PATH_MAX] = ""; - if ( config.use_deep_storage ) + Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length); + } + else if (bytes_read+n_bytes == (int)frame_header.image_length) { - struct tm *time = localtime( &frame_header.event_time ); - snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); + Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length); } else { - snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id ); + Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes); } + } + bytes_read+= n_bytes; + } while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) ); - static char path[PATH_MAX] = ""; - snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id ); - Debug( 1, "Got image, writing to %s", path ); + // Print errors if there was a problem + if ( n_bytes < 1 ) + { + Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length); + if ( n_bytes < 0 ) + { + Error( "Can't read frame image data: %s", strerror(errno) ); + } + else + { + Warning( "Socket closed at remote end" ); + } + ReopenSocket( sd, monitor->Id() ); + continue; + } - FILE *fd = 0; - if ( (fd = fopen( path, "w" )) < 0 ) - { - Error( "Can't fopen '%s': %s", path, strerror(errno) ); - exit( -1 ); - } - if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) ) - { - Error( "Can't fwrite image data: %s", strerror(errno) ); - exit( -1 ); - } - fclose( fd ); + static char subpath[PATH_MAX] = ""; + if ( config.use_deep_storage ) + { + struct tm *time = localtime( &frame_header.event_time ); + snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); + } + else + { + snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id ); + } - sigprocmask( SIG_UNBLOCK, &block_set, 0 ); - } - logTerm(); - zmDbClose(); + static char path[PATH_MAX] = ""; + snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id ); + Debug( 1, "Got image, writing to %s", path ); + + FILE *fd = 0; + if ( (fd = fopen( path, "w" )) < 0 ) + { + Error( "Can't fopen '%s': %s", path, strerror(errno) ); + exit( -1 ); + } + if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) ) + { + Error( "Can't fwrite image data: %s", strerror(errno) ); + exit( -1 ); + } + fclose( fd ); + + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + } + logTerm(); + zmDbClose(); } diff --git a/src/zmf.h b/src/zmf.h index f00ffa891..211577309 100644 --- a/src/zmf.h +++ b/src/zmf.h @@ -22,11 +22,11 @@ struct FrameHeader { - unsigned long event_id; - time_t event_time; - unsigned long frame_id; - bool alarm_frame; - unsigned long image_length; + unsigned long event_id; + time_t event_time; + unsigned long frame_id; + bool alarm_frame; + unsigned long image_length; }; #endif // ZMFILE_H diff --git a/src/zms.cpp b/src/zms.cpp index 9a7fcc941..b4caf0d35 100644 --- a/src/zms.cpp +++ b/src/zms.cpp @@ -28,318 +28,318 @@ bool ValidateAccess( User *user, int mon_id ) { - bool allowed = true; + bool allowed = true; - if ( mon_id > 0 ) - { - if ( user->getStream() < User::PERM_VIEW ) - allowed = false; - if ( !user->canAccess( mon_id ) ) - allowed = false; - } - else - { - if ( user->getEvents() < User::PERM_VIEW ) - allowed = false; - } - if ( !allowed ) - { - Error( "Error, insufficient privileges for requested action" ); - exit( -1 ); - } - return( allowed ); + if ( mon_id > 0 ) + { + if ( user->getStream() < User::PERM_VIEW ) + allowed = false; + if ( !user->canAccess( mon_id ) ) + allowed = false; + } + else + { + if ( user->getEvents() < User::PERM_VIEW ) + allowed = false; + } + if ( !allowed ) + { + Error( "Error, insufficient privileges for requested action" ); + exit( -1 ); + } + return( allowed ); } int main( int argc, const char *argv[] ) { - self = argv[0]; + self = argv[0]; - srand( getpid() * time( 0 ) ); + srand( getpid() * time( 0 ) ); - enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR; - enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG; - char format[32] = ""; - int monitor_id = 0; - time_t event_time = 0; - int event_id = 0; - int frame_id = 1; - unsigned int scale = 100; - unsigned int rate = 100; - double maxfps = 10.0; - unsigned int bitrate = 100000; - unsigned int ttl = 0; - EventStream::StreamMode replay = EventStream::MODE_SINGLE; - char username[64] = ""; - char password[64] = ""; - char auth[64] = ""; - unsigned int connkey = 0; - unsigned int playback_buffer = 0; + enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR; + enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG; + char format[32] = ""; + int monitor_id = 0; + time_t event_time = 0; + int event_id = 0; + int frame_id = 1; + unsigned int scale = 100; + unsigned int rate = 100; + double maxfps = 10.0; + unsigned int bitrate = 100000; + unsigned int ttl = 0; + EventStream::StreamMode replay = EventStream::MODE_SINGLE; + char username[64] = ""; + char password[64] = ""; + char auth[64] = ""; + unsigned int connkey = 0; + unsigned int playback_buffer = 0; - bool nph = false; - const char *basename = strrchr( argv[0], '/' ); - if (basename) //if we found a / lets skip past it - basename++; - else //argv[0] will not always contain the full path, but rather just the script name - basename = argv[0]; - const char *nph_prefix = "nph-"; - if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) ) - { - nph = true; - } - - zmLoadConfig(); + bool nph = false; + const char *basename = strrchr( argv[0], '/' ); + if (basename) //if we found a / lets skip past it + basename++; + else //argv[0] will not always contain the full path, but rather just the script name + basename = argv[0]; + const char *nph_prefix = "nph-"; + if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) ) + { + nph = true; + } + + zmLoadConfig(); - logInit( "zms" ); - - ssedetect(); + logInit( "zms" ); + + ssedetect(); - zmSetDefaultTermHandler(); - zmSetDefaultDieHandler(); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); - const char *query = getenv( "QUERY_STRING" ); - if ( query ) - { - Debug( 1, "Query: %s", query ); - - char temp_query[1024]; - strncpy( temp_query, query, sizeof(temp_query) ); - char *q_ptr = temp_query; - char *parms[16]; // Shouldn't be more than this - int parm_no = 0; - while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) ) - { - parm_no++; - q_ptr = NULL; - } - - for ( int p = 0; p < parm_no; p++ ) - { - char *name = strtok( parms[p], "=" ); - char *value = strtok( NULL, "=" ); - if ( !value ) - value = (char *)""; - if ( !strcmp( name, "source" ) ) - { - source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR; - } - else if ( !strcmp( name, "mode" ) ) - { - mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG; - mode = !strcmp( value, "raw" )?ZMS_RAW:mode; - mode = !strcmp( value, "zip" )?ZMS_ZIP:mode; - mode = !strcmp( value, "single" )?ZMS_SINGLE:mode; - } - else if ( !strcmp( name, "format" ) ) - strncpy( format, value, sizeof(format) ); - else if ( !strcmp( name, "monitor" ) ) - monitor_id = atoi( value ); - else if ( !strcmp( name, "time" ) ) - event_time = atoi( value ); - else if ( !strcmp( name, "event" ) ) - event_id = strtoull( value, (char **)NULL, 10 ); - else if ( !strcmp( name, "frame" ) ) - frame_id = strtoull( value, (char **)NULL, 10 ); - else if ( !strcmp( name, "scale" ) ) - scale = atoi( value ); - else if ( !strcmp( name, "rate" ) ) - rate = atoi( value ); - else if ( !strcmp( name, "maxfps" ) ) - maxfps = atof( value ); - else if ( !strcmp( name, "bitrate" ) ) - bitrate = atoi( value ); - else if ( !strcmp( name, "ttl" ) ) - ttl = atoi(value); - else if ( !strcmp( name, "replay" ) ) - { - replay = !strcmp( value, "gapless" )?EventStream::MODE_ALL_GAPLESS:EventStream::MODE_SINGLE; - replay = !strcmp( value, "all" )?EventStream::MODE_ALL:replay; - } - else if ( !strcmp( name, "connkey" ) ) - connkey = atoi(value); - else if ( !strcmp( name, "buffer" ) ) - playback_buffer = atoi(value); - else if ( config.opt_use_auth ) - { - if ( strcmp( config.auth_relay, "none" ) == 0 ) - { - if ( !strcmp( name, "user" ) ) - { - strncpy( username, value, sizeof(username) ); - } - } - else - { - //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) - { - if ( !strcmp( name, "auth" ) ) - { - strncpy( auth, value, sizeof(auth) ); - } - } - //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) - { - if ( !strcmp( name, "user" ) ) - { - strncpy( username, value, sizeof(username) ); - } - if ( !strcmp( name, "pass" ) ) - { - strncpy( password, value, sizeof(password) ); - } - } - } - } - } - } - - if ( config.opt_use_auth ) - { - User *user = 0; - - if ( strcmp( config.auth_relay, "none" ) == 0 ) - { - if ( *username ) - { - user = zmLoadUser( username ); - } - } - else - { - //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) - { - if ( *auth ) - { - user = zmLoadAuthUser( auth, config.auth_hash_ips ); - } - } - //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) - { - if ( *username && *password ) - { - user = zmLoadUser( username, password ); - } - } - } - if ( !user ) - { - Error( "Unable to authenticate user" ); - logTerm(); - zmDbClose(); - return( -1 ); - } - ValidateAccess( user, monitor_id ); - } - - setbuf( stdout, 0 ); - if ( nph ) - { - fprintf( stdout, "HTTP/1.0 200 OK\r\n" ); - } - fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION ); - - time_t now = time( 0 ); - char date_string[64]; - strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) ); - - fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" ); - fprintf( stdout, "Last-Modified: %s\r\n", date_string ); - fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" ); - fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" ); - fprintf( stdout, "Pragma: no-cache\r\n"); - // Removed as causing more problems than it fixed. - //if ( !nph ) - //{ - //fprintf( stdout, "Content-Length: 0\r\n"); - //} - - if ( source == ZMS_MONITOR ) - { - MonitorStream stream; - stream.setStreamScale( scale ); - stream.setStreamReplayRate( rate ); - stream.setStreamMaxFPS( maxfps ); - stream.setStreamTTL( ttl ); - stream.setStreamQueue( connkey ); - stream.setStreamBuffer( playback_buffer ); - if ( ! stream.setStreamStart( monitor_id ) ) { - Error( "Unable to connect to zmc process for monitor %d", monitor_id ); - fprintf( stderr, "Unable to connect to zmc process. Please ensure that it is running." ); - logTerm(); - zmDbClose(); - return( -1 ); - } - - if ( mode == ZMS_JPEG ) - { - stream.setStreamType( MonitorStream::STREAM_JPEG ); - } - else if ( mode == ZMS_RAW ) - { - stream.setStreamType( MonitorStream::STREAM_RAW ); - } - else if ( mode == ZMS_ZIP ) - { - stream.setStreamType( MonitorStream::STREAM_ZIP ); - } - else if ( mode == ZMS_SINGLE ) - { - stream.setStreamType( MonitorStream::STREAM_SINGLE ); - } - else - { -#if HAVE_LIBAVCODEC - stream.setStreamFormat( format ); - stream.setStreamBitrate( bitrate ); - stream.setStreamType( MonitorStream::STREAM_MPEG ); -#else // HAVE_LIBAVCODEC - Error( "MPEG streaming of '%s' attempted while disabled", query ); - fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" ); - logTerm(); - zmDbClose(); - return( -1 ); -#endif // HAVE_LIBAVCODEC - } - stream.runStream(); - } - else if ( source == ZMS_EVENT ) + const char *query = getenv( "QUERY_STRING" ); + if ( query ) + { + Debug( 1, "Query: %s", query ); + + char temp_query[1024]; + strncpy( temp_query, query, sizeof(temp_query) ); + char *q_ptr = temp_query; + char *parms[16]; // Shouldn't be more than this + int parm_no = 0; + while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) ) { - EventStream stream; - stream.setStreamScale( scale ); - stream.setStreamReplayRate( rate ); - stream.setStreamMaxFPS( maxfps ); - stream.setStreamMode( replay ); - stream.setStreamQueue( connkey ); - if ( monitor_id && event_time ) - { - stream.setStreamStart( monitor_id, event_time ); - } - else - { - stream.setStreamStart( event_id, frame_id ); - } - if ( mode == ZMS_JPEG ) - { - stream.setStreamType( EventStream::STREAM_JPEG ); - } - else - { -#if HAVE_LIBAVCODEC - stream.setStreamFormat( format ); - stream.setStreamBitrate( bitrate ); - stream.setStreamType( EventStream::STREAM_MPEG ); -#else // HAVE_LIBAVCODEC - Error( "MPEG streaming of '%s' attempted while disabled", query ); - fprintf( stderr, "MPEG streaming is disabled.\nYou should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality.\n" ); - logTerm(); - zmDbClose(); - return( -1 ); -#endif // HAVE_LIBAVCODEC - } - stream.runStream(); + parm_no++; + q_ptr = NULL; } + + for ( int p = 0; p < parm_no; p++ ) + { + char *name = strtok( parms[p], "=" ); + char *value = strtok( NULL, "=" ); + if ( !value ) + value = (char *)""; + if ( !strcmp( name, "source" ) ) + { + source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR; + } + else if ( !strcmp( name, "mode" ) ) + { + mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG; + mode = !strcmp( value, "raw" )?ZMS_RAW:mode; + mode = !strcmp( value, "zip" )?ZMS_ZIP:mode; + mode = !strcmp( value, "single" )?ZMS_SINGLE:mode; + } + else if ( !strcmp( name, "format" ) ) + strncpy( format, value, sizeof(format) ); + else if ( !strcmp( name, "monitor" ) ) + monitor_id = atoi( value ); + else if ( !strcmp( name, "time" ) ) + event_time = atoi( value ); + else if ( !strcmp( name, "event" ) ) + event_id = strtoull( value, (char **)NULL, 10 ); + else if ( !strcmp( name, "frame" ) ) + frame_id = strtoull( value, (char **)NULL, 10 ); + else if ( !strcmp( name, "scale" ) ) + scale = atoi( value ); + else if ( !strcmp( name, "rate" ) ) + rate = atoi( value ); + else if ( !strcmp( name, "maxfps" ) ) + maxfps = atof( value ); + else if ( !strcmp( name, "bitrate" ) ) + bitrate = atoi( value ); + else if ( !strcmp( name, "ttl" ) ) + ttl = atoi(value); + else if ( !strcmp( name, "replay" ) ) + { + replay = !strcmp( value, "gapless" )?EventStream::MODE_ALL_GAPLESS:EventStream::MODE_SINGLE; + replay = !strcmp( value, "all" )?EventStream::MODE_ALL:replay; + } + else if ( !strcmp( name, "connkey" ) ) + connkey = atoi(value); + else if ( !strcmp( name, "buffer" ) ) + playback_buffer = atoi(value); + else if ( config.opt_use_auth ) + { + if ( strcmp( config.auth_relay, "none" ) == 0 ) + { + if ( !strcmp( name, "user" ) ) + { + strncpy( username, value, sizeof(username) ); + } + } + else + { + //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) + { + if ( !strcmp( name, "auth" ) ) + { + strncpy( auth, value, sizeof(auth) ); + } + } + //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) + { + if ( !strcmp( name, "user" ) ) + { + strncpy( username, value, sizeof(username) ); + } + if ( !strcmp( name, "pass" ) ) + { + strncpy( password, value, sizeof(password) ); + } + } + } + } + } + } - logTerm(); - zmDbClose(); + if ( config.opt_use_auth ) + { + User *user = 0; - return( 0 ); + if ( strcmp( config.auth_relay, "none" ) == 0 ) + { + if ( *username ) + { + user = zmLoadUser( username ); + } + } + else + { + //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) + { + if ( *auth ) + { + user = zmLoadAuthUser( auth, config.auth_hash_ips ); + } + } + //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) + { + if ( *username && *password ) + { + user = zmLoadUser( username, password ); + } + } + } + if ( !user ) + { + Error( "Unable to authenticate user" ); + logTerm(); + zmDbClose(); + return( -1 ); + } + ValidateAccess( user, monitor_id ); + } + + setbuf( stdout, 0 ); + if ( nph ) + { + fprintf( stdout, "HTTP/1.0 200 OK\r\n" ); + } + fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION ); + + time_t now = time( 0 ); + char date_string[64]; + strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) ); + + fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" ); + fprintf( stdout, "Last-Modified: %s\r\n", date_string ); + fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" ); + fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" ); + fprintf( stdout, "Pragma: no-cache\r\n"); + // Removed as causing more problems than it fixed. + //if ( !nph ) + //{ + //fprintf( stdout, "Content-Length: 0\r\n"); + //} + + if ( source == ZMS_MONITOR ) + { + MonitorStream stream; + stream.setStreamScale( scale ); + stream.setStreamReplayRate( rate ); + stream.setStreamMaxFPS( maxfps ); + stream.setStreamTTL( ttl ); + stream.setStreamQueue( connkey ); + stream.setStreamBuffer( playback_buffer ); + if ( ! stream.setStreamStart( monitor_id ) ) { + Error( "Unable to connect to zmc process for monitor %d", monitor_id ); + fprintf( stderr, "Unable to connect to zmc process. Please ensure that it is running." ); + logTerm(); + zmDbClose(); + return( -1 ); + } + + if ( mode == ZMS_JPEG ) + { + stream.setStreamType( MonitorStream::STREAM_JPEG ); + } + else if ( mode == ZMS_RAW ) + { + stream.setStreamType( MonitorStream::STREAM_RAW ); + } + else if ( mode == ZMS_ZIP ) + { + stream.setStreamType( MonitorStream::STREAM_ZIP ); + } + else if ( mode == ZMS_SINGLE ) + { + stream.setStreamType( MonitorStream::STREAM_SINGLE ); + } + else + { +#if HAVE_LIBAVCODEC + stream.setStreamFormat( format ); + stream.setStreamBitrate( bitrate ); + stream.setStreamType( MonitorStream::STREAM_MPEG ); +#else // HAVE_LIBAVCODEC + Error( "MPEG streaming of '%s' attempted while disabled", query ); + fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" ); + logTerm(); + zmDbClose(); + return( -1 ); +#endif // HAVE_LIBAVCODEC + } + stream.runStream(); + } + else if ( source == ZMS_EVENT ) + { + EventStream stream; + stream.setStreamScale( scale ); + stream.setStreamReplayRate( rate ); + stream.setStreamMaxFPS( maxfps ); + stream.setStreamMode( replay ); + stream.setStreamQueue( connkey ); + if ( monitor_id && event_time ) + { + stream.setStreamStart( monitor_id, event_time ); + } + else + { + stream.setStreamStart( event_id, frame_id ); + } + if ( mode == ZMS_JPEG ) + { + stream.setStreamType( EventStream::STREAM_JPEG ); + } + else + { +#if HAVE_LIBAVCODEC + stream.setStreamFormat( format ); + stream.setStreamBitrate( bitrate ); + stream.setStreamType( EventStream::STREAM_MPEG ); +#else // HAVE_LIBAVCODEC + Error( "MPEG streaming of '%s' attempted while disabled", query ); + fprintf( stderr, "MPEG streaming is disabled.\nYou should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality.\n" ); + logTerm(); + zmDbClose(); + return( -1 ); +#endif // HAVE_LIBAVCODEC + } + stream.runStream(); + } + + logTerm(); + zmDbClose(); + + return( 0 ); } diff --git a/src/zmstreamer.cpp b/src/zmstreamer.cpp index a16e50704..b33c61246 100644 --- a/src/zmstreamer.cpp +++ b/src/zmstreamer.cpp @@ -50,16 +50,16 @@ running the eyeZm app. =head1 OPTIONS - -e - Specify output mode: mpeg/jpg/zip/single/raw. - -o - Specify output format. - -u - Specify buffer size in ms. - -f - Specify maximum framerate. - -s - Specify scale. - -b - Specify bitrate. - -m - Specify monitor id. - -d - 0 = off, 1 = no streaming, 2 = with streaming. - -i, -?, -h - Display usage information - -v - Print the installed version of ZoneMinder + -e - Specify output mode: mpeg/jpg/zip/single/raw. + -o - Specify output format. + -u - Specify buffer size in ms. + -f - Specify maximum framerate. + -s - Specify scale. + -b - Specify bitrate. + -m - Specify monitor id. + -d - 0 = off, 1 = no streaming, 2 = with streaming. + -i, -?, -h - Display usage information + -v - Print the installed version of ZoneMinder =cut @@ -92,161 +92,161 @@ running the eyeZm app. #define ZMS_DEFAULT_BUFFER 1000 int main(int argc, char** argv) { - self = argv[0]; - // Set initial values to the default values - int debug = ZMS_DEFAULT_DEBUG; - int id = ZMS_DEFAULT_ID; - int bitrate = ZMS_DEFAULT_BITRATE; - int scale = ZMS_DEFAULT_SCALE; - char mode[32]; - sprintf(mode, "%s", ZMS_DEFAULT_MODE); - char format[32]; - sprintf(format, "%s", ZMS_DEFAULT_FORMAT); - double maxfps = ZMS_DEFAULT_FPS; - int buffer = ZMS_DEFAULT_BUFFER; + self = argv[0]; + // Set initial values to the default values + int debug = ZMS_DEFAULT_DEBUG; + int id = ZMS_DEFAULT_ID; + int bitrate = ZMS_DEFAULT_BITRATE; + int scale = ZMS_DEFAULT_SCALE; + char mode[32]; + sprintf(mode, "%s", ZMS_DEFAULT_MODE); + char format[32]; + sprintf(format, "%s", ZMS_DEFAULT_FORMAT); + double maxfps = ZMS_DEFAULT_FPS; + int buffer = ZMS_DEFAULT_BUFFER; - // Parse command-line options - int arg; - while ((arg = getopt(argc, argv, OPTIONS)) != -1) { - switch (arg) { - case 'e': - sprintf(mode, "%s", optarg); - break; - case 'o': - sprintf(format, "%s", optarg); - break; - case 'u': - buffer = atoi(optarg); - break; - case 'f': - maxfps = atof(optarg); - break; - case 's': - scale = atoi(optarg); - break; - case 'b': - bitrate = atoi(optarg); - break; - case 'm': - id = atoi(optarg); - break; - case 'd': - debug = atoi(optarg); - break; - case 'h': - case 'i': - case '?': - printf("-e : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE); - printf("-o : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT); - printf("-u : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER); - printf("-f : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS); - printf("-s : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE); - printf("-b : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE); - printf("-m : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID); - printf("-d : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n"); - printf("-i or -? or -h: This information\n"); - printf("-v : This installed version of ZoneMinder\n"); - return EXIT_SUCCESS; - case 'v': - std::cout << ZM_VERSION << "\n"; - exit(0); - } + // Parse command-line options + int arg; + while ((arg = getopt(argc, argv, OPTIONS)) != -1) { + switch (arg) { + case 'e': + sprintf(mode, "%s", optarg); + break; + case 'o': + sprintf(format, "%s", optarg); + break; + case 'u': + buffer = atoi(optarg); + break; + case 'f': + maxfps = atof(optarg); + break; + case 's': + scale = atoi(optarg); + break; + case 'b': + bitrate = atoi(optarg); + break; + case 'm': + id = atoi(optarg); + break; + case 'd': + debug = atoi(optarg); + break; + case 'h': + case 'i': + case '?': + printf("-e : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE); + printf("-o : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT); + printf("-u : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER); + printf("-f : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS); + printf("-s : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE); + printf("-b : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE); + printf("-m : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID); + printf("-d : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n"); + printf("-i or -? or -h: This information\n"); + printf("-v : This installed version of ZoneMinder\n"); + return EXIT_SUCCESS; + case 'v': + std::cout << ZM_VERSION << "\n"; + exit(0); } + } - // Set stream type - StreamBase::StreamType streamtype; - if (!strcasecmp("raw", mode)) - streamtype = MonitorStream::STREAM_RAW; - else if (!strcasecmp("mpeg", mode)) - streamtype = MonitorStream::STREAM_MPEG; - else if (!strcasecmp("jpg", mode)) - streamtype = MonitorStream::STREAM_JPEG; - else if (!strcasecmp("single", mode)) - streamtype = MonitorStream::STREAM_SINGLE; - else if (!strcasecmp("zip", mode)) - streamtype = MonitorStream::STREAM_ZIP; - else - streamtype = MonitorStream::STREAM_MPEG; + // Set stream type + StreamBase::StreamType streamtype; + if (!strcasecmp("raw", mode)) + streamtype = MonitorStream::STREAM_RAW; + else if (!strcasecmp("mpeg", mode)) + streamtype = MonitorStream::STREAM_MPEG; + else if (!strcasecmp("jpg", mode)) + streamtype = MonitorStream::STREAM_JPEG; + else if (!strcasecmp("single", mode)) + streamtype = MonitorStream::STREAM_SINGLE; + else if (!strcasecmp("zip", mode)) + streamtype = MonitorStream::STREAM_ZIP; + else + streamtype = MonitorStream::STREAM_MPEG; - if (debug) { - // Show stream parameters - printf("Stream parameters:\n"); - switch (streamtype) { - case MonitorStream::STREAM_MPEG: - printf("Output mode (-e) = %s\n", "mpeg"); - printf("Output format (-o) = %s\n", format); - break; - default: - printf("Output mode (-e) = %s\n", mode); - } - printf("Buffer size (-u) = %d ms\n", buffer); - printf("Maximum FPS (-f) = %lf FPS\n", maxfps); - printf("Scale (-s) = %d%%\n", scale); - printf("Bitrate (-b) = %d bps\n", bitrate); - printf("Monitor Id (-m) = %d\n", id); + if (debug) { + // Show stream parameters + printf("Stream parameters:\n"); + switch (streamtype) { + case MonitorStream::STREAM_MPEG: + printf("Output mode (-e) = %s\n", "mpeg"); + printf("Output format (-o) = %s\n", format); + break; + default: + printf("Output mode (-e) = %s\n", mode); } + printf("Buffer size (-u) = %d ms\n", buffer); + printf("Maximum FPS (-f) = %lf FPS\n", maxfps); + printf("Scale (-s) = %d%%\n", scale); + printf("Bitrate (-b) = %d bps\n", bitrate); + printf("Monitor Id (-m) = %d\n", id); + } - if (debug) { - // Set ZM debugger to print to stdout - printf("Setting up ZoneMinder debugger to print to stdout..."); - setenv("ZM_DBG_PRINT", "1", 1); - printf("Done.\n"); - } - - // Loading ZM configurations - printf("Loading ZoneMinder configurations..."); - zmLoadConfig(); + if (debug) { + // Set ZM debugger to print to stdout + printf("Setting up ZoneMinder debugger to print to stdout..."); + setenv("ZM_DBG_PRINT", "1", 1); printf("Done.\n"); + } - logInit("zmstreamer"); - - ssedetect(); + // Loading ZM configurations + printf("Loading ZoneMinder configurations..."); + zmLoadConfig(); + printf("Done.\n"); - // Setting stream parameters - MonitorStream stream; - stream.setStreamScale(scale); // default = 100 (scale) - stream.setStreamReplayRate(100); // default = 100 (rate) - stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps) - if (debug) stream.setStreamTTL(1); - else stream.setStreamTTL(0); // default = 0 (ttl) - stream.setStreamQueue(0); // default = 0 (connkey) - stream.setStreamBuffer(buffer); // default = 0 (buffer) - stream.setStreamStart(id); // default = 0 (monitor_id) - stream.setStreamType(streamtype); - if (streamtype == MonitorStream::STREAM_MPEG) { + logInit("zmstreamer"); + + ssedetect(); + + // Setting stream parameters + MonitorStream stream; + stream.setStreamScale(scale); // default = 100 (scale) + stream.setStreamReplayRate(100); // default = 100 (rate) + stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps) + if (debug) stream.setStreamTTL(1); + else stream.setStreamTTL(0); // default = 0 (ttl) + stream.setStreamQueue(0); // default = 0 (connkey) + stream.setStreamBuffer(buffer); // default = 0 (buffer) + stream.setStreamStart(id); // default = 0 (monitor_id) + stream.setStreamType(streamtype); + if (streamtype == MonitorStream::STREAM_MPEG) { #if HAVE_LIBAVCODEC - if (debug) printf("HAVE_LIBAVCODEC is set\n"); - stream.setStreamFormat(format); // default = "" (format) - stream.setStreamBitrate(bitrate); // default = 100000 (bitrate) + if (debug) printf("HAVE_LIBAVCODEC is set\n"); + stream.setStreamFormat(format); // default = "" (format) + stream.setStreamBitrate(bitrate); // default = 100000 (bitrate) #else - fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n"); - logTerm(); - zmDbClose(); - return EXIT_FAILURE; -#endif - } - - if (debug != 1) { - if (debug) printf("Running stream..."); - - // Output headers - fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION); - time_t now = time(0); - char date_string[64]; - strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); - fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"); - fprintf(stdout, "Last-Modified: %s\r\n", date_string); - fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n"); - fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n"); - fprintf(stdout, "Pragma: no-cache\r\n"); - - // Run stream - stream.runStream(); - } - if (debug) printf("Done.\n"); - + fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n"); logTerm(); zmDbClose(); + return EXIT_FAILURE; +#endif + } - return (EXIT_SUCCESS); + if (debug != 1) { + if (debug) printf("Running stream..."); + + // Output headers + fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION); + time_t now = time(0); + char date_string[64]; + strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); + fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"); + fprintf(stdout, "Last-Modified: %s\r\n", date_string); + fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n"); + fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n"); + fprintf(stdout, "Pragma: no-cache\r\n"); + + // Run stream + stream.runStream(); + } + if (debug) printf("Done.\n"); + + logTerm(); + zmDbClose(); + + return (EXIT_SUCCESS); } diff --git a/src/zmu.cpp b/src/zmu.cpp index a1e8887bd..88a781073 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -41,46 +41,46 @@ problems. =head1 OPTIONS General options: - -v, --verbose - Produce more verbose output - -l, --list - List the current status of active (or all with -v) monitors - -h, --help - Display usage information - -v, --version - Print the installed version of ZoneMinder + -v, --verbose - Produce more verbose output + -l, --list - List the current status of active (or all with -v) monitors + -h, --help - Display usage information + -v, --version - Print the installed version of ZoneMinder Options for use with devices: - -d, --device [device_path] - Get the current video device settings for [device_path] or all devices - -V, --version - Set the Video 4 Linux API version to use for the query, use 1 or 2 - -q, --query - Query the current settings for the device + -d, --device [device_path] - Get the current video device settings for [device_path] or all devices + -V, --version - Set the Video 4 Linux API version to use for the query, use 1 or 2 + -q, --query - Query the current settings for the device Options for use with monitors: - -m, --monitor - Specify which monitor to address, default 1 if absent - -q, --query - Query the current settings for the monitor - -s, --state - Output the current monitor state, 0 = idle, 1 = prealarm, 2 = alarm, - 3 = alert, 4 = tape - -B, --brightness [value] - Output the current brightness, set to value if given - -C, --contrast [value] - Output the current contrast, set to value if given - -H, --hue [value] - Output the current hue, set to value if given - -O, --colour [value] - Output the current colour, set to value if given - -i, --image [image_index] - Write captured image to disk as .jpg, last image captured - or specified ring buffer index if given. - -S, --scale - With --image specify any scaling (in %%) to be applied to the image - -t, --timestamp [image_index] - Output captured image timestamp, last image captured or specified - ring buffer index if given - -R, --read_index - Output ring buffer read index - -W, --write_index - Output ring buffer write index - -e, --event - Output last event index - -f, --fps - Output last Frames Per Second captured reading - -z, --zones - Write last captured image overlaid with zones to -Zones.jpg - -a, --alarm - Force alarm in monitor, this will trigger recording until cancelled with -c - -n, --noalarm - Force no alarms in monitor, this will prevent alarms until cancelled with -c - -c, --cancel - Cancel a forced alarm/noalarm in monitor, required after being enabled with -a or -n - -L, --reload - Signal monitor to reload settings - -E, --enable - Enable detection, wake monitor up - -D, --disable - Disable detection, put monitor to sleep - -u, --suspend - Suspend detection, useful to prevent bogus alarms when panning etc - -r, --resume - Resume detection after a suspend - -U, --username - When running in authenticated mode the username and - -P, --password - password combination of the given user - -A, --auth - Pass authentication hash string instead of user details + -m, --monitor - Specify which monitor to address, default 1 if absent + -q, --query - Query the current settings for the monitor + -s, --state - Output the current monitor state, 0 = idle, 1 = prealarm, 2 = alarm, + 3 = alert, 4 = tape + -B, --brightness [value] - Output the current brightness, set to value if given + -C, --contrast [value] - Output the current contrast, set to value if given + -H, --hue [value] - Output the current hue, set to value if given + -O, --colour [value] - Output the current colour, set to value if given + -i, --image [image_index] - Write captured image to disk as .jpg, last image captured + or specified ring buffer index if given. + -S, --scale - With --image specify any scaling (in %%) to be applied to the image + -t, --timestamp [image_index] - Output captured image timestamp, last image captured or specified + ring buffer index if given + -R, --read_index - Output ring buffer read index + -W, --write_index - Output ring buffer write index + -e, --event - Output last event index + -f, --fps - Output last Frames Per Second captured reading + -z, --zones - Write last captured image overlaid with zones to -Zones.jpg + -a, --alarm - Force alarm in monitor, this will trigger recording until cancelled with -c + -n, --noalarm - Force no alarms in monitor, this will prevent alarms until cancelled with -c + -c, --cancel - Cancel a forced alarm/noalarm in monitor, required after being enabled with -a or -n + -L, --reload - Signal monitor to reload settings + -E, --enable - Enable detection, wake monitor up + -D, --disable - Disable detection, put monitor to sleep + -u, --suspend - Suspend detection, useful to prevent bogus alarms when panning etc + -r, --resume - Resume detection after a suspend + -U, --username - When running in authenticated mode the username and + -P, --password - password combination of the given user + -A, --auth - Pass authentication hash string instead of user details =cut @@ -97,740 +97,740 @@ Options for use with monitors: void Usage( int status=-1 ) { - fprintf( stderr, "zmu <-d device_path> [-v] [function] [-U -P]\n" ); - fprintf( stderr, "zmu <-m monitor_id> [-v] [function] [-U -P]\n" ); - fprintf( stderr, "General options:\n" ); - fprintf( stderr, " -h, --help : This screen\n" ); - fprintf( stderr, " -v, --verbose : Produce more verbose output\n" ); - fprintf( stderr, " -l, --list : List the current status of active (or all with -v) monitors\n" ); - fprintf( stderr, "Options for use with devices:\n" ); - fprintf( stderr, " -d, --device [device_path] : Get the current video device settings for [device_path] or all devices\n" ); - fprintf( stderr, " -V, --version : Set the Video 4 Linux API version to use for the query, use 1 or 2\n" ); - fprintf( stderr, " -q, --query : Query the current settings for the device\n" ); - fprintf( stderr, "Options for use with monitors:\n" ); - fprintf( stderr, " -m, --monitor : Specify which monitor to address, default 1 if absent\n" ); - fprintf( stderr, " -q, --query : Query the current settings for the monitor\n" ); - fprintf( stderr, " -s, --state : Output the current monitor state, 0 = idle, 1 = prealarm, 2 = alarm,\n" ); - fprintf( stderr, " 3 = alert, 4 = tape\n" ); - fprintf( stderr, " -B, --brightness [value] : Output the current brightness, set to value if given \n" ); - fprintf( stderr, " -C, --contrast [value] : Output the current contrast, set to value if given \n" ); - fprintf( stderr, " -H, --hue [value] : Output the current hue, set to value if given \n" ); - fprintf( stderr, " -O, --colour [value] : Output the current colour, set to value if given \n" ); - fprintf( stderr, " -i, --image [image_index] : Write captured image to disk as .jpg, last image captured\n" ); - fprintf( stderr, " or specified ring buffer index if given.\n" ); - fprintf( stderr, " -S, --scale : With --image specify any scaling (in %%) to be applied to the image\n" ); - fprintf( stderr, " -t, --timestamp [image_index] : Output captured image timestamp, last image captured or specified\n" ); - fprintf( stderr, " ring buffer index if given\n" ); - fprintf( stderr, " -R, --read_index : Output ring buffer read index\n" ); - fprintf( stderr, " -W, --write_index : Output ring buffer write index\n" ); - fprintf( stderr, " -e, --event : Output last event index\n" ); - fprintf( stderr, " -f, --fps : Output last Frames Per Second captured reading\n" ); - fprintf( stderr, " -z, --zones : Write last captured image overlaid with zones to -Zones.jpg\n" ); - fprintf( stderr, " -a, --alarm : Force alarm in monitor, this will trigger recording until cancelled with -c\n" ); - fprintf( stderr, " -n, --noalarm : Force no alarms in monitor, this will prevent alarms until cancelled with -c\n" ); - fprintf( stderr, " -c, --cancel : Cancel a forced alarm/noalarm in monitor, required after being enabled with -a or -n\n" ); - fprintf( stderr, " -L, --reload : Signal monitor to reload settings\n" ); - fprintf( stderr, " -E, --enable : Enable detection, wake monitor up\n" ); - fprintf( stderr, " -D, --disable : Disable detection, put monitor to sleep\n" ); - fprintf( stderr, " -u, --suspend : Suspend detection, useful to prevent bogus alarms when panning etc\n" ); - fprintf( stderr, " -r, --resume : Resume detection after a suspend\n" ); - fprintf( stderr, " -U, --username : When running in authenticated mode the username and\n" ); - fprintf( stderr, " -P, --password : password combination of the given user\n" ); - fprintf( stderr, " -A, --auth : Pass authentication hash string instead of user details\n" ); + fprintf( stderr, "zmu <-d device_path> [-v] [function] [-U -P]\n" ); + fprintf( stderr, "zmu <-m monitor_id> [-v] [function] [-U -P]\n" ); + fprintf( stderr, "General options:\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + fprintf( stderr, " -v, --verbose : Produce more verbose output\n" ); + fprintf( stderr, " -l, --list : List the current status of active (or all with -v) monitors\n" ); + fprintf( stderr, "Options for use with devices:\n" ); + fprintf( stderr, " -d, --device [device_path] : Get the current video device settings for [device_path] or all devices\n" ); + fprintf( stderr, " -V, --version : Set the Video 4 Linux API version to use for the query, use 1 or 2\n" ); + fprintf( stderr, " -q, --query : Query the current settings for the device\n" ); + fprintf( stderr, "Options for use with monitors:\n" ); + fprintf( stderr, " -m, --monitor : Specify which monitor to address, default 1 if absent\n" ); + fprintf( stderr, " -q, --query : Query the current settings for the monitor\n" ); + fprintf( stderr, " -s, --state : Output the current monitor state, 0 = idle, 1 = prealarm, 2 = alarm,\n" ); + fprintf( stderr, " 3 = alert, 4 = tape\n" ); + fprintf( stderr, " -B, --brightness [value] : Output the current brightness, set to value if given \n" ); + fprintf( stderr, " -C, --contrast [value] : Output the current contrast, set to value if given \n" ); + fprintf( stderr, " -H, --hue [value] : Output the current hue, set to value if given \n" ); + fprintf( stderr, " -O, --colour [value] : Output the current colour, set to value if given \n" ); + fprintf( stderr, " -i, --image [image_index] : Write captured image to disk as .jpg, last image captured\n" ); + fprintf( stderr, " or specified ring buffer index if given.\n" ); + fprintf( stderr, " -S, --scale : With --image specify any scaling (in %%) to be applied to the image\n" ); + fprintf( stderr, " -t, --timestamp [image_index] : Output captured image timestamp, last image captured or specified\n" ); + fprintf( stderr, " ring buffer index if given\n" ); + fprintf( stderr, " -R, --read_index : Output ring buffer read index\n" ); + fprintf( stderr, " -W, --write_index : Output ring buffer write index\n" ); + fprintf( stderr, " -e, --event : Output last event index\n" ); + fprintf( stderr, " -f, --fps : Output last Frames Per Second captured reading\n" ); + fprintf( stderr, " -z, --zones : Write last captured image overlaid with zones to -Zones.jpg\n" ); + fprintf( stderr, " -a, --alarm : Force alarm in monitor, this will trigger recording until cancelled with -c\n" ); + fprintf( stderr, " -n, --noalarm : Force no alarms in monitor, this will prevent alarms until cancelled with -c\n" ); + fprintf( stderr, " -c, --cancel : Cancel a forced alarm/noalarm in monitor, required after being enabled with -a or -n\n" ); + fprintf( stderr, " -L, --reload : Signal monitor to reload settings\n" ); + fprintf( stderr, " -E, --enable : Enable detection, wake monitor up\n" ); + fprintf( stderr, " -D, --disable : Disable detection, put monitor to sleep\n" ); + fprintf( stderr, " -u, --suspend : Suspend detection, useful to prevent bogus alarms when panning etc\n" ); + fprintf( stderr, " -r, --resume : Resume detection after a suspend\n" ); + fprintf( stderr, " -U, --username : When running in authenticated mode the username and\n" ); + fprintf( stderr, " -P, --password : password combination of the given user\n" ); + fprintf( stderr, " -A, --auth : Pass authentication hash string instead of user details\n" ); - exit( status ); + exit( status ); } typedef enum { - ZMU_BOGUS = 0x00000000, - ZMU_STATE = 0x00000001, - ZMU_IMAGE = 0x00000002, - ZMU_TIME = 0x00000004, - ZMU_READ_IDX = 0x00000008, - ZMU_WRITE_IDX = 0x00000010, - ZMU_EVENT = 0x00000020, - ZMU_FPS = 0x00000040, - ZMU_ZONES = 0x00000080, - ZMU_ALARM = 0x00000100, - ZMU_NOALARM = 0x00000200, - ZMU_CANCEL = 0x00000400, - ZMU_QUERY = 0x00000800, - ZMU_BRIGHTNESS = 0x00001000, - ZMU_CONTRAST = 0x00002000, - ZMU_HUE = 0x00004000, - ZMU_COLOUR = 0x00008000, - ZMU_RELOAD = 0x00010000, - ZMU_ENABLE = 0x00100000, - ZMU_DISABLE = 0x00200000, - ZMU_SUSPEND = 0x00400000, - ZMU_RESUME = 0x00800000, - ZMU_LIST = 0x10000000, + ZMU_BOGUS = 0x00000000, + ZMU_STATE = 0x00000001, + ZMU_IMAGE = 0x00000002, + ZMU_TIME = 0x00000004, + ZMU_READ_IDX = 0x00000008, + ZMU_WRITE_IDX = 0x00000010, + ZMU_EVENT = 0x00000020, + ZMU_FPS = 0x00000040, + ZMU_ZONES = 0x00000080, + ZMU_ALARM = 0x00000100, + ZMU_NOALARM = 0x00000200, + ZMU_CANCEL = 0x00000400, + ZMU_QUERY = 0x00000800, + ZMU_BRIGHTNESS = 0x00001000, + ZMU_CONTRAST = 0x00002000, + ZMU_HUE = 0x00004000, + ZMU_COLOUR = 0x00008000, + ZMU_RELOAD = 0x00010000, + ZMU_ENABLE = 0x00100000, + ZMU_DISABLE = 0x00200000, + ZMU_SUSPEND = 0x00400000, + ZMU_RESUME = 0x00800000, + ZMU_LIST = 0x10000000, } Function; bool ValidateAccess( User *user, int mon_id, int function ) { - bool allowed = true; - if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) - { - if ( user->getStream() < User::PERM_VIEW ) - allowed = false; - } - if ( function & ZMU_EVENT ) - { - if ( user->getEvents() < User::PERM_VIEW ) - allowed = false; - } - if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) ) - { - if ( user->getMonitors() < User::PERM_VIEW ) - allowed = false; - } - if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) ) - { - if ( user->getMonitors() < User::PERM_EDIT ) - allowed = false; - } - if ( mon_id > 0 ) - { - if ( !user->canAccess( mon_id ) ) - { - allowed = false; - } - } - if ( !allowed ) - { - fprintf( stderr, "Error, insufficient privileges for requested action\n" ); - exit( -1 ); - } - return( allowed ); + bool allowed = true; + if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) + { + if ( user->getStream() < User::PERM_VIEW ) + allowed = false; + } + if ( function & ZMU_EVENT ) + { + if ( user->getEvents() < User::PERM_VIEW ) + allowed = false; + } + if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) ) + { + if ( user->getMonitors() < User::PERM_VIEW ) + allowed = false; + } + if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) ) + { + if ( user->getMonitors() < User::PERM_EDIT ) + allowed = false; + } + if ( mon_id > 0 ) + { + if ( !user->canAccess( mon_id ) ) + { + allowed = false; + } + } + if ( !allowed ) + { + fprintf( stderr, "Error, insufficient privileges for requested action\n" ); + exit( -1 ); + } + return( allowed ); } int main( int argc, char *argv[] ) { - if ( access(ZM_CONFIG, R_OK) != 0 ) - { - fprintf( stderr, "Can't open %s: %s\n", ZM_CONFIG, strerror(errno) ); - exit( -1 ); - } + if ( access(ZM_CONFIG, R_OK) != 0 ) + { + fprintf( stderr, "Can't open %s: %s\n", ZM_CONFIG, strerror(errno) ); + exit( -1 ); + } - self = argv[0]; + self = argv[0]; - srand( getpid() * time( 0 ) ); + srand( getpid() * time( 0 ) ); - static struct option long_options[] = { - {"device", 2, 0, 'd'}, - {"monitor", 1, 0, 'm'}, - {"verbose", 0, 0, 'v'}, - {"image", 2, 0, 'i'}, - {"scale", 1, 0, 'S'}, - {"timestamp", 2, 0, 't'}, - {"state", 0, 0, 's'}, - {"brightness", 2, 0, 'B'}, - {"contrast", 2, 0, 'C'}, - {"hue", 2, 0, 'H'}, - {"contrast", 2, 0, 'O'}, - {"read_index", 0, 0, 'R'}, - {"write_index", 0, 0, 'W'}, - {"event", 0, 0, 'e'}, - {"fps", 0, 0, 'f'}, - {"zones", 2, 0, 'z'}, - {"alarm", 0, 0, 'a'}, - {"noalarm", 0, 0, 'n'}, - {"cancel", 0, 0, 'c'}, - {"reload", 0, 0, 'L'}, - {"enable", 0, 0, 'E'}, - {"disable", 0, 0, 'D'}, - {"suspend", 0, 0, 'u'}, - {"resume", 0, 0, 'r'}, - {"query", 0, 0, 'q'}, - {"username", 1, 0, 'U'}, - {"password", 1, 0, 'P'}, - {"auth", 1, 0, 'A'}, - {"version", 1, 0, 'V'}, - {"help", 0, 0, 'h'}, - {"list", 0, 0, 'l'}, - {0, 0, 0, 0} - }; + static struct option long_options[] = { + {"device", 2, 0, 'd'}, + {"monitor", 1, 0, 'm'}, + {"verbose", 0, 0, 'v'}, + {"image", 2, 0, 'i'}, + {"scale", 1, 0, 'S'}, + {"timestamp", 2, 0, 't'}, + {"state", 0, 0, 's'}, + {"brightness", 2, 0, 'B'}, + {"contrast", 2, 0, 'C'}, + {"hue", 2, 0, 'H'}, + {"contrast", 2, 0, 'O'}, + {"read_index", 0, 0, 'R'}, + {"write_index", 0, 0, 'W'}, + {"event", 0, 0, 'e'}, + {"fps", 0, 0, 'f'}, + {"zones", 2, 0, 'z'}, + {"alarm", 0, 0, 'a'}, + {"noalarm", 0, 0, 'n'}, + {"cancel", 0, 0, 'c'}, + {"reload", 0, 0, 'L'}, + {"enable", 0, 0, 'E'}, + {"disable", 0, 0, 'D'}, + {"suspend", 0, 0, 'u'}, + {"resume", 0, 0, 'r'}, + {"query", 0, 0, 'q'}, + {"username", 1, 0, 'U'}, + {"password", 1, 0, 'P'}, + {"auth", 1, 0, 'A'}, + {"version", 1, 0, 'V'}, + {"help", 0, 0, 'h'}, + {"list", 0, 0, 'l'}, + {0, 0, 0, 0} + }; - const char *device = 0; - int mon_id = 0; - bool verbose = false; - int function = ZMU_BOGUS; + const char *device = 0; + int mon_id = 0; + bool verbose = false; + int function = ZMU_BOGUS; - int image_idx = -1; - int scale = -1; - int brightness = -1; - int contrast = -1; - int hue = -1; - int colour = -1; - char *zoneString = 0; - char *username = 0; - char *password = 0; - char *auth = 0; + int image_idx = -1; + int scale = -1; + int brightness = -1; + int contrast = -1; + int hue = -1; + int colour = -1; + char *zoneString = 0; + char *username = 0; + char *password = 0; + char *auth = 0; #if ZM_HAS_V4L #if ZM_HAS_V4L2 - int v4lVersion = 2; + int v4lVersion = 2; #elif ZM_HAS_V4L1 - int v4lVersion = 1; + int v4lVersion = 1; #endif // ZM_HAS_V4L2/1 #endif // ZM_HAS_V4L - while (1) - { - int option_index = 0; + while (1) + { + int option_index = 0; - int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index); - if (c == -1) - { - break; - } + int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index); + if (c == -1) + { + break; + } - switch (c) - { - case 'd': - if ( optarg ) - device = optarg; - break; - case 'm': - mon_id = atoi(optarg); - break; - case 'v': - verbose = true; - break; - case 's': - function |= ZMU_STATE; - break; - case 'i': - function |= ZMU_IMAGE; - if ( optarg ) - image_idx = atoi( optarg ); - break; - case 'S': - scale = atoi(optarg); - break; - case 't': - function |= ZMU_TIME; - if ( optarg ) - image_idx = atoi( optarg ); - break; - case 'R': - function |= ZMU_READ_IDX; - break; - case 'W': - function |= ZMU_WRITE_IDX; - break; - case 'e': - function |= ZMU_EVENT; - break; - case 'f': - function |= ZMU_FPS; - break; - case 'z': - function |= ZMU_ZONES; - if ( optarg ) - zoneString = optarg; - break; - case 'a': - function |= ZMU_ALARM; - break; - case 'n': - function |= ZMU_NOALARM; - break; - case 'c': - function |= ZMU_CANCEL; - break; - case 'L': - function |= ZMU_RELOAD; - break; - case 'E': - function |= ZMU_ENABLE; - break; - case 'D': - function |= ZMU_DISABLE; - break; - case 'u': - function |= ZMU_SUSPEND; - break; - case 'r': - function |= ZMU_RESUME; - break; - case 'q': - function |= ZMU_QUERY; - break; - case 'B': - function |= ZMU_BRIGHTNESS; - if ( optarg ) - brightness = atoi( optarg ); - break; - case 'C': - function |= ZMU_CONTRAST; - if ( optarg ) - contrast = atoi( optarg ); - break; - case 'H': - function |= ZMU_HUE; - if ( optarg ) - hue = atoi( optarg ); - break; - case 'O': - function |= ZMU_COLOUR; - if ( optarg ) - colour = atoi( optarg ); - break; - case 'U': - username = optarg; - break; - case 'P': - password = optarg; - break; - case 'A': - auth = optarg; - break; + switch (c) + { + case 'd': + if ( optarg ) + device = optarg; + break; + case 'm': + mon_id = atoi(optarg); + break; + case 'v': + verbose = true; + break; + case 's': + function |= ZMU_STATE; + break; + case 'i': + function |= ZMU_IMAGE; + if ( optarg ) + image_idx = atoi( optarg ); + break; + case 'S': + scale = atoi(optarg); + break; + case 't': + function |= ZMU_TIME; + if ( optarg ) + image_idx = atoi( optarg ); + break; + case 'R': + function |= ZMU_READ_IDX; + break; + case 'W': + function |= ZMU_WRITE_IDX; + break; + case 'e': + function |= ZMU_EVENT; + break; + case 'f': + function |= ZMU_FPS; + break; + case 'z': + function |= ZMU_ZONES; + if ( optarg ) + zoneString = optarg; + break; + case 'a': + function |= ZMU_ALARM; + break; + case 'n': + function |= ZMU_NOALARM; + break; + case 'c': + function |= ZMU_CANCEL; + break; + case 'L': + function |= ZMU_RELOAD; + break; + case 'E': + function |= ZMU_ENABLE; + break; + case 'D': + function |= ZMU_DISABLE; + break; + case 'u': + function |= ZMU_SUSPEND; + break; + case 'r': + function |= ZMU_RESUME; + break; + case 'q': + function |= ZMU_QUERY; + break; + case 'B': + function |= ZMU_BRIGHTNESS; + if ( optarg ) + brightness = atoi( optarg ); + break; + case 'C': + function |= ZMU_CONTRAST; + if ( optarg ) + contrast = atoi( optarg ); + break; + case 'H': + function |= ZMU_HUE; + if ( optarg ) + hue = atoi( optarg ); + break; + case 'O': + function |= ZMU_COLOUR; + if ( optarg ) + colour = atoi( optarg ); + break; + case 'U': + username = optarg; + break; + case 'P': + password = optarg; + break; + case 'A': + auth = optarg; + break; #if ZM_HAS_V4L - case 'V': - v4lVersion = (atoi(optarg)==1)?1:2; - break; + case 'V': + v4lVersion = (atoi(optarg)==1)?1:2; + break; #endif // ZM_HAS_V4L - case 'h': - Usage( 0 ); - break; - case 'l': - function |= ZMU_LIST; - break; - case '?': - Usage(); - break; - default: - //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); - break; - } - } + case 'h': + Usage( 0 ); + break; + case 'l': + function |= ZMU_LIST; + break; + case '?': + Usage(); + break; + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } - if (optind < argc) - { - fprintf( stderr, "Extraneous options, " ); - while (optind < argc) - fprintf( stderr, "%s ", argv[optind++]); - fprintf( stderr, "\n"); - Usage(); - } + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + fprintf( stderr, "%s ", argv[optind++]); + fprintf( stderr, "\n"); + Usage(); + } - if ( device && !(function&ZMU_QUERY) ) - { - fprintf( stderr, "Error, -d option cannot be used with this option\n" ); - Usage(); - } - if ( scale != -1 && !(function&ZMU_IMAGE) ) - { - fprintf( stderr, "Error, -S option cannot be used with this option\n" ); - Usage(); - } - //printf( "Monitor %d, Function %d\n", mon_id, function ); + if ( device && !(function&ZMU_QUERY) ) + { + fprintf( stderr, "Error, -d option cannot be used with this option\n" ); + Usage(); + } + if ( scale != -1 && !(function&ZMU_IMAGE) ) + { + fprintf( stderr, "Error, -S option cannot be used with this option\n" ); + Usage(); + } + //printf( "Monitor %d, Function %d\n", mon_id, function ); - zmLoadConfig(); + zmLoadConfig(); - logInit( "zmu" ); + logInit( "zmu" ); - zmSetDefaultTermHandler(); - zmSetDefaultDieHandler(); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); - User *user = 0; + User *user = 0; - if ( config.opt_use_auth ) - { - if ( strcmp( config.auth_relay, "none" ) == 0 ) - { - if ( !username ) - { - fprintf( stderr, "Error, username must be supplied\n" ); - exit( -1 ); - } + if ( config.opt_use_auth ) + { + if ( strcmp( config.auth_relay, "none" ) == 0 ) + { + if ( !username ) + { + fprintf( stderr, "Error, username must be supplied\n" ); + exit( -1 ); + } - if ( username ) - { - user = zmLoadUser( username ); - } - } - else - { - if ( !(username && password) && !auth ) - { - fprintf( stderr, "Error, username and password or auth string must be supplied\n" ); - exit( -1 ); - } + if ( username ) + { + user = zmLoadUser( username ); + } + } + else + { + if ( !(username && password) && !auth ) + { + fprintf( stderr, "Error, username and password or auth string must be supplied\n" ); + exit( -1 ); + } - //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) - { - if ( auth ) - { - user = zmLoadAuthUser( auth, false ); - } - } - //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) - { - if ( username && password ) - { - user = zmLoadUser( username, password ); - } - } - } - if ( !user ) - { - fprintf( stderr, "Error, unable to authenticate user\n" ); - exit( -1 ); - } - ValidateAccess( user, mon_id, function ); - } - + //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) + { + if ( auth ) + { + user = zmLoadAuthUser( auth, false ); + } + } + //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) + { + if ( username && password ) + { + user = zmLoadUser( username, password ); + } + } + } + if ( !user ) + { + fprintf( stderr, "Error, unable to authenticate user\n" ); + exit( -1 ); + } + ValidateAccess( user, mon_id, function ); + } + - if ( mon_id > 0 ) - { - Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY ); - if ( monitor ) - { - if ( verbose ) - { - printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() ); - } - if ( ! monitor->connect() ) { - Error( "Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name() ); - exit( -1 ); - } + if ( mon_id > 0 ) + { + Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY ); + if ( monitor ) + { + if ( verbose ) + { + printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() ); + } + if ( ! monitor->connect() ) { + Error( "Can't connect to capture daemon: %d %s", monitor->Id(), monitor->Name() ); + exit( -1 ); + } - char separator = ' '; - bool have_output = false; - if ( function & ZMU_STATE ) - { - Monitor::State state = monitor->GetState(); - if ( verbose ) - printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") ); - else - { - if ( have_output ) printf( "%c", separator ); - printf( "%d", state ); - have_output = true; - } - } - if ( function & ZMU_TIME ) - { - struct timeval timestamp = monitor->GetTimestamp( image_idx ); - if ( verbose ) - { - char timestamp_str[64] = "None"; - if ( timestamp.tv_sec ) - strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( ×tamp.tv_sec ) ); - if ( image_idx == -1 ) - printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 ); - else - printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 ); - } - else - { - if ( have_output ) printf( "%c", separator ); - printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 ); - have_output = true; - } - } - if ( function & ZMU_READ_IDX ) - { - if ( verbose ) - printf( "Last read index: %d\n", monitor->GetLastReadIndex() ); - else - { - if ( have_output ) printf( "%c", separator ); - printf( "%d", monitor->GetLastReadIndex() ); - have_output = true; - } - } - if ( function & ZMU_WRITE_IDX ) - { - if ( verbose ) - printf( "Last write index: %d\n", monitor->GetLastWriteIndex() ); - else - { - if ( have_output ) printf( "%c", separator ); - printf( "%d", monitor->GetLastWriteIndex() ); - have_output = true; - } - } - if ( function & ZMU_EVENT ) - { - if ( verbose ) - printf( "Last event id: %d\n", monitor->GetLastEvent() ); - else - { - if ( have_output ) printf( "%c", separator ); - printf( "%d", monitor->GetLastEvent() ); - have_output = true; - } - } - if ( function & ZMU_FPS ) - { - if ( verbose ) - printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() ); - else - { - if ( have_output ) printf( "%c", separator ); - printf( "%.2f", monitor->GetFPS() ); - have_output = true; - } - } - if ( function & ZMU_IMAGE ) - { - if ( verbose ) - { - if ( image_idx == -1 ) - printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() ); - else - printf( "Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id() ); - if ( scale != -1 ) - printf( ", scaling by %d%%", scale ); - printf( "\n" ); - } - monitor->GetImage( image_idx, scale>0?scale:100 ); - } - if ( function & ZMU_ZONES ) - { - if ( verbose ) - printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() ); - monitor->DumpZoneImage( zoneString ); - } - if ( function & ZMU_ALARM ) - { - if ( verbose ) - printf( "Forcing alarm on\n" ); - monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" ); - } - if ( function & ZMU_NOALARM ) - { - if ( verbose ) - printf( "Forcing alarm off\n" ); - monitor->ForceAlarmOff(); - } - if ( function & ZMU_CANCEL ) - { - if ( verbose ) - printf( "Cancelling forced alarm on/off\n" ); - monitor->CancelForced(); - } - if ( function & ZMU_RELOAD ) - { - if ( verbose ) - printf( "Reloading monitor settings\n" ); - monitor->actionReload(); - } - if ( function & ZMU_ENABLE ) - { - if ( verbose ) - printf( "Enabling event generation\n" ); - monitor->actionEnable(); - } - if ( function & ZMU_DISABLE ) - { - if ( verbose ) - printf( "Disabling event generation\n" ); - monitor->actionDisable(); - } - if ( function & ZMU_SUSPEND ) - { - if ( verbose ) - printf( "Suspending event generation\n" ); - monitor->actionSuspend(); - } - if ( function & ZMU_RESUME ) - { - if ( verbose ) - printf( "Resuming event generation\n" ); - monitor->actionResume(); - } - if ( function & ZMU_QUERY ) - { - char monString[16382] = ""; - monitor->DumpSettings( monString, verbose ); - printf( "%s\n", monString ); - } - if ( function & ZMU_BRIGHTNESS ) - { - if ( verbose ) - { - if ( brightness >= 0 ) - printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) ); - else - printf( "Current brightness: %d\n", monitor->actionBrightness() ); - } - else - { - if ( have_output ) printf( "%c", separator ); - if ( brightness >= 0 ) - printf( "%d", monitor->actionBrightness( brightness ) ); - else - printf( "%d", monitor->actionBrightness() ); - have_output = true; - } - } - if ( function & ZMU_CONTRAST ) - { - if ( verbose ) - { - if ( contrast >= 0 ) - printf( "New brightness: %d\n", monitor->actionContrast( contrast ) ); - else - printf( "Current contrast: %d\n", monitor->actionContrast() ); - } - else - { - if ( have_output ) printf( "%c", separator ); - if ( contrast >= 0 ) - printf( "%d", monitor->actionContrast( contrast ) ); - else - printf( "%d", monitor->actionContrast() ); - have_output = true; - } - } - if ( function & ZMU_HUE ) - { - if ( verbose ) - { - if ( hue >= 0 ) - printf( "New hue: %d\n", monitor->actionHue( hue ) ); - else - printf( "Current hue: %d\n", monitor->actionHue() ); - } - else - { - if ( have_output ) printf( "%c", separator ); - if ( hue >= 0 ) - printf( "%d", monitor->actionHue( hue ) ); - else - printf( "%d", monitor->actionHue() ); - have_output = true; - } - } - if ( function & ZMU_COLOUR ) - { - if ( verbose ) - { - if ( colour >= 0 ) - printf( "New colour: %d\n", monitor->actionColour( colour ) ); - else - printf( "Current colour: %d\n", monitor->actionColour() ); - } - else - { - if ( have_output ) printf( "%c", separator ); - if ( colour >= 0 ) - printf( "%d", monitor->actionColour( colour ) ); - else - printf( "%d", monitor->actionColour() ); - have_output = true; - } - } - if ( have_output ) - { - printf( "\n" ); - } - if ( !function ) - { - Usage(); - } - delete monitor; - } - else - { - fprintf( stderr, "Error, invalid monitor id %d\n", mon_id ); - exit( -1 ); - } - } - else - { - if ( function & ZMU_QUERY ) - { + char separator = ' '; + bool have_output = false; + if ( function & ZMU_STATE ) + { + Monitor::State state = monitor->GetState(); + if ( verbose ) + printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", state ); + have_output = true; + } + } + if ( function & ZMU_TIME ) + { + struct timeval timestamp = monitor->GetTimestamp( image_idx ); + if ( verbose ) + { + char timestamp_str[64] = "None"; + if ( timestamp.tv_sec ) + strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( ×tamp.tv_sec ) ); + if ( image_idx == -1 ) + printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 ); + else + printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 ); + } + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 ); + have_output = true; + } + } + if ( function & ZMU_READ_IDX ) + { + if ( verbose ) + printf( "Last read index: %d\n", monitor->GetLastReadIndex() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", monitor->GetLastReadIndex() ); + have_output = true; + } + } + if ( function & ZMU_WRITE_IDX ) + { + if ( verbose ) + printf( "Last write index: %d\n", monitor->GetLastWriteIndex() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", monitor->GetLastWriteIndex() ); + have_output = true; + } + } + if ( function & ZMU_EVENT ) + { + if ( verbose ) + printf( "Last event id: %d\n", monitor->GetLastEvent() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", monitor->GetLastEvent() ); + have_output = true; + } + } + if ( function & ZMU_FPS ) + { + if ( verbose ) + printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%.2f", monitor->GetFPS() ); + have_output = true; + } + } + if ( function & ZMU_IMAGE ) + { + if ( verbose ) + { + if ( image_idx == -1 ) + printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() ); + else + printf( "Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id() ); + if ( scale != -1 ) + printf( ", scaling by %d%%", scale ); + printf( "\n" ); + } + monitor->GetImage( image_idx, scale>0?scale:100 ); + } + if ( function & ZMU_ZONES ) + { + if ( verbose ) + printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() ); + monitor->DumpZoneImage( zoneString ); + } + if ( function & ZMU_ALARM ) + { + if ( verbose ) + printf( "Forcing alarm on\n" ); + monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" ); + } + if ( function & ZMU_NOALARM ) + { + if ( verbose ) + printf( "Forcing alarm off\n" ); + monitor->ForceAlarmOff(); + } + if ( function & ZMU_CANCEL ) + { + if ( verbose ) + printf( "Cancelling forced alarm on/off\n" ); + monitor->CancelForced(); + } + if ( function & ZMU_RELOAD ) + { + if ( verbose ) + printf( "Reloading monitor settings\n" ); + monitor->actionReload(); + } + if ( function & ZMU_ENABLE ) + { + if ( verbose ) + printf( "Enabling event generation\n" ); + monitor->actionEnable(); + } + if ( function & ZMU_DISABLE ) + { + if ( verbose ) + printf( "Disabling event generation\n" ); + monitor->actionDisable(); + } + if ( function & ZMU_SUSPEND ) + { + if ( verbose ) + printf( "Suspending event generation\n" ); + monitor->actionSuspend(); + } + if ( function & ZMU_RESUME ) + { + if ( verbose ) + printf( "Resuming event generation\n" ); + monitor->actionResume(); + } + if ( function & ZMU_QUERY ) + { + char monString[16382] = ""; + monitor->DumpSettings( monString, verbose ); + printf( "%s\n", monString ); + } + if ( function & ZMU_BRIGHTNESS ) + { + if ( verbose ) + { + if ( brightness >= 0 ) + printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) ); + else + printf( "Current brightness: %d\n", monitor->actionBrightness() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( brightness >= 0 ) + printf( "%d", monitor->actionBrightness( brightness ) ); + else + printf( "%d", monitor->actionBrightness() ); + have_output = true; + } + } + if ( function & ZMU_CONTRAST ) + { + if ( verbose ) + { + if ( contrast >= 0 ) + printf( "New brightness: %d\n", monitor->actionContrast( contrast ) ); + else + printf( "Current contrast: %d\n", monitor->actionContrast() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( contrast >= 0 ) + printf( "%d", monitor->actionContrast( contrast ) ); + else + printf( "%d", monitor->actionContrast() ); + have_output = true; + } + } + if ( function & ZMU_HUE ) + { + if ( verbose ) + { + if ( hue >= 0 ) + printf( "New hue: %d\n", monitor->actionHue( hue ) ); + else + printf( "Current hue: %d\n", monitor->actionHue() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( hue >= 0 ) + printf( "%d", monitor->actionHue( hue ) ); + else + printf( "%d", monitor->actionHue() ); + have_output = true; + } + } + if ( function & ZMU_COLOUR ) + { + if ( verbose ) + { + if ( colour >= 0 ) + printf( "New colour: %d\n", monitor->actionColour( colour ) ); + else + printf( "Current colour: %d\n", monitor->actionColour() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( colour >= 0 ) + printf( "%d", monitor->actionColour( colour ) ); + else + printf( "%d", monitor->actionColour() ); + have_output = true; + } + } + if ( have_output ) + { + printf( "\n" ); + } + if ( !function ) + { + Usage(); + } + delete monitor; + } + else + { + fprintf( stderr, "Error, invalid monitor id %d\n", mon_id ); + exit( -1 ); + } + } + else + { + if ( function & ZMU_QUERY ) + { #if ZM_HAS_V4L - char vidString[0x10000] = ""; - bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose ); - printf( "%s", vidString ); - exit( ok?0:-1 ); + char vidString[0x10000] = ""; + bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose ); + printf( "%s", vidString ); + exit( ok?0:-1 ); #else // ZM_HAS_V4L - fprintf( stderr, "Error, video4linux is required for device querying\n" ); - exit( -1 ); + fprintf( stderr, "Error, video4linux is required for device querying\n" ); + exit( -1 ); #endif // ZM_HAS_V4L - } + } - if ( function & ZMU_LIST ) - { - char sql[ZM_SQL_SML_BUFSIZ]; - strncpy( sql, "select Id, Function+0 from Monitors", sizeof(sql) ); - if ( !verbose ) - { - strncat( sql, " where Function != 'None'", sizeof(sql)-strlen(sql) ); - } - strncat( sql, " order by Id asc", sizeof(sql)-strlen(sql) ); + if ( function & ZMU_LIST ) + { + char sql[ZM_SQL_SML_BUFSIZ]; + strncpy( sql, "select Id, Function+0 from Monitors", sizeof(sql) ); + if ( !verbose ) + { + strncat( sql, " where Function != 'None'", sizeof(sql)-strlen(sql) ); + } + strncat( sql, " order by Id asc", sizeof(sql)-strlen(sql) ); - if ( mysql_query( &dbconn, sql ) ) - { - Error( "Can't run query: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } - MYSQL_RES *result = mysql_store_result( &dbconn ); - if ( !result ) - { - Error( "Can't use query result: %s", mysql_error( &dbconn ) ); - exit( mysql_errno( &dbconn ) ); - } - int n_monitors = mysql_num_rows( result ); - Debug( 1, "Got %d monitors", n_monitors ); + MYSQL_RES *result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); - printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" ); - for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) - { - int mon_id = atoi(dbrow[0]); - int function = atoi(dbrow[1]); - if ( !user || user->canAccess( mon_id ) ) - { - if ( function > 1 ) - { - Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY ); - if ( monitor && monitor->connect() ) - { - struct timeval tv = monitor->GetTimestamp(); - printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", - monitor->Id(), - function, - monitor->GetState(), - monitor->GetTriggerState(), - tv.tv_sec, tv.tv_usec/10000, - monitor->GetLastReadIndex(), - monitor->GetLastWriteIndex(), - monitor->GetLastEvent(), - monitor->GetFPS() - ); - delete monitor; - } - } - else - { - struct timeval tv = { 0, 0 }; - printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", - mon_id, - function, - 0, - 0, - tv.tv_sec, tv.tv_usec/10000, - 0, - 0, - 0, - 0.0 - ); - } - } - } - mysql_free_result( result ); - } - } - delete user; + printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" ); + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int mon_id = atoi(dbrow[0]); + int function = atoi(dbrow[1]); + if ( !user || user->canAccess( mon_id ) ) + { + if ( function > 1 ) + { + Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY ); + if ( monitor && monitor->connect() ) + { + struct timeval tv = monitor->GetTimestamp(); + printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", + monitor->Id(), + function, + monitor->GetState(), + monitor->GetTriggerState(), + tv.tv_sec, tv.tv_usec/10000, + monitor->GetLastReadIndex(), + monitor->GetLastWriteIndex(), + monitor->GetLastEvent(), + monitor->GetFPS() + ); + delete monitor; + } + } + else + { + struct timeval tv = { 0, 0 }; + printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", + mon_id, + function, + 0, + 0, + tv.tv_sec, tv.tv_usec/10000, + 0, + 0, + 0, + 0.0 + ); + } + } + } + mysql_free_result( result ); + } + } + delete user; - logTerm(); - zmDbClose(); + logTerm(); + zmDbClose(); - return( 0 ); + return( 0 ); }