diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | include/aspeed/JTABLES.H | 299 | ||||
-rw-r--r-- | include/ast_jpeg_decoder.hpp | 1547 | ||||
-rw-r--r-- | include/kvm_websocket.hpp | 173 | ||||
-rw-r--r-- | include/security_headers_middleware.hpp | 7 | ||||
-rw-r--r-- | include/web_kvm.hpp | 422 | ||||
-rw-r--r-- | src/getvideo_main.cpp | 79 | ||||
-rw-r--r-- | src/webserver_main.cpp | 4 |
8 files changed, 182 insertions, 2354 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6756575c27..a15e7197c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ option (BUILD_STATIC_LIBS "Built static libraries" ON) option (YOCTO_DEPENDENCIES "Use YOCTO dependencies system" OFF) option (BMCWEB_ENABLE_KVM "Enable the KVM host video WebSocket. Path is - '/kvmws'. Video is from the BMC's '/dev/video' device." ON) + '/kvm/0'. Video is from the BMC's '/dev/video' device." ON) option (BMCWEB_ENABLE_DBUS_REST "Enable Phosphor REST (D-Bus) APIs. Paths directly map Phosphor D-Bus object paths, for example, '/xyz/openbmc_project/logging/entry/enumerate'. See @@ -248,9 +248,6 @@ target_link_libraries (bmcweb sdbusplus) target_link_libraries (bmcweb tinyxml2) install (TARGETS bmcweb DESTINATION bin) -add_executable (getvideo src/getvideo_main.cpp) -target_link_libraries (getvideo pthread) - target_compile_definitions ( bmcweb PRIVATE $<$<BOOL:${BMCWEB_ENABLE_KVM}>: -DBMCWEB_ENABLE_KVM> diff --git a/include/aspeed/JTABLES.H b/include/aspeed/JTABLES.H deleted file mode 100644 index 641fcfb76a..0000000000 --- a/include/aspeed/JTABLES.H +++ /dev/null @@ -1,299 +0,0 @@ -#pragma once
-static const unsigned char zigzag[64] = {
- 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42,
- 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53,
- 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60,
- 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63};
-
-static const unsigned char dezigzag[64 + 15] = {
- 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40,
- 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36,
- 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61,
- 54, 47, 55, 62, 63,
- // let corrupt input sample past end
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63};
-
-static const unsigned char *stdLuminanceQt;
-static const unsigned char *stdChrominanceQt;
-
-// Standard Huffman tables (cf. JPEG standard section K.3) */
-
-static const unsigned char stdDcLuminanceNrcodes[17] = {
- 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0};
-static const unsigned char stdDcLuminanceValues[12] = {0, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 10, 11};
-
-static const unsigned char stdDcChrominanceNrcodes[17] = {
- 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
-static const unsigned char stdDcChrominanceValues[12] = {0, 1, 2, 3, 4, 5,
- 6, 7, 8, 9, 10, 11};
-
-static const unsigned char stdAcLuminanceNrcodes[17] = {
- 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d};
-static const unsigned char stdAcLuminanceValues[162] = {
- 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};
-
-static const unsigned char stdAcChrominanceNrcodes[17] = {
- 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77};
-static const unsigned char stdAcChrominanceValues[162] = {
- 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};
-
-static const unsigned short int dcLuminanceHuffmancode[13 * 2] = {
- /* 0 */ 0x0000, 0,
- /* 1 */ 0x4000, 2,
- /* 2 */ 0x6000, 3,
- /* 3 */ 0x8000, 3,
- /* 4 */ 0xA000, 3,
- /* 5 */ 0xC000, 3,
- /* 6 */ 0xE000, 3,
- /* 7 */ 0xF000, 4,
- /* 8 */ 0xF800, 5,
- /* 9 */ 0xFC00, 6,
- /* 10 */ 0xFE00, 7,
- /* 11 */ 0xFF00, 8,
- /* 12 */ 0xFFFF, 9,
-};
-
-static const unsigned short int dcChrominanceHuffmancode[13 * 2] = {
- /* 0 */ 0x0000, 0,
- /* 1 */ 0x4000, 2,
- /* 2 */ 0x8000, 2,
- /* 3 */ 0xC000, 2,
- /* 4 */ 0xE000, 3,
- /* 5 */ 0xF000, 4,
- /* 6 */ 0xF800, 5,
- /* 7 */ 0xFC00, 6,
- /* 8 */ 0xFE00, 7,
- /* 9 */ 0xFF00, 8,
- /* 10 */ 0xFF80, 9,
- /* 11 */ 0xFFC0, 10,
- /* 12 */ 0xFFFF, 11,
-};
-
-static const unsigned short int acLuminanceHuffmancode[39 * 2] = {
- /* 0 */ 0x0000, 0,
- /* 1 */ 0x4000, 2,
- /* 2 */ 0x8000, 2,
- /* 3 */ 0xA000, 3,
- /* 4 */ 0xB000, 4,
- /* 5 */ 0xC000, 4,
- /* 6 */ 0xD000, 4,
- /* 7 */ 0xD800, 5,
- /* 8 */ 0xE000, 5,
- /* 9 */ 0xE800, 5,
- /* 10 */ 0xEC00, 6,
- /* 11 */ 0xF000, 6,
- /* 12 */ 0xF200, 7,
- /* 13 */ 0xF400, 7,
- /* 14 */ 0xF600, 7,
- /* 15 */ 0xF800, 7,
- /* 16 */ 0xF900, 8,
- /* 17 */ 0xFA00, 8,
- /* 18 */ 0xFB00, 8,
- /* 19 */ 0xFB80, 9,
- /* 20 */ 0xFC00, 9,
- /* 21 */ 0xFC80, 9,
- /* 22 */ 0xFD00, 9,
- /* 23 */ 0xFD80, 9,
- /* 24 */ 0xFDC0, 10,
- /* 25 */ 0xFE00, 10,
- /* 26 */ 0xFE40, 10,
- /* 27 */ 0xFE80, 10,
- /* 28 */ 0xFEC0, 10,
- /* 29 */ 0xFEE0, 11,
- /* 30 */ 0xFF00, 11,
- /* 31 */ 0xFF20, 11,
- /* 32 */ 0xFF40, 11,
- /* 33 */ 0xFF50, 12,
- /* 34 */ 0xFF60, 12,
- /* 35 */ 0xFF70, 12,
- /* 36 */ 0xFF80, 12,
- /* 37 */ 0xFF82, 15,
- /* 38 */ 0xFFFF, 16,
-};
-
-static const unsigned short int acChrominanceHuffmancode[45 * 2] = {
- /* 0 */ 0x0000, 0,
- /* 1 */ 0x4000, 2,
- /* 2 */ 0x8000, 2,
- /* 3 */ 0xA000, 3,
- /* 4 */ 0xB000, 4,
- /* 5 */ 0xC000, 4,
- /* 6 */ 0xC800, 5,
- /* 7 */ 0xD000, 5,
- /* 8 */ 0xD800, 5,
- /* 9 */ 0xE000, 5,
- /* 10 */ 0xE400, 6,
- /* 11 */ 0xE800, 6,
- /* 12 */ 0xEC00, 6,
- /* 13 */ 0xF000, 6,
- /* 14 */ 0xF200, 7,
- /* 15 */ 0xF400, 7,
- /* 16 */ 0xF600, 7,
- /* 17 */ 0xF700, 8,
- /* 18 */ 0xF800, 8,
- /* 19 */ 0xF900, 8,
- /* 20 */ 0xFA00, 8,
- /* 21 */ 0xFA80, 9,
- /* 22 */ 0xFB00, 9,
- /* 23 */ 0xFB80, 9,
- /* 24 */ 0xFC00, 9,
- /* 25 */ 0xFC80, 9,
- /* 26 */ 0xFD00, 9,
- /* 27 */ 0xFD80, 9,
- /* 28 */ 0xFDC0, 10,
- /* 29 */ 0xFE00, 10,
- /* 30 */ 0xFE40, 10,
- /* 31 */ 0xFE80, 10,
- /* 32 */ 0xFEC0, 10,
- /* 33 */ 0xFEE0, 11,
- /* 34 */ 0xFF00, 11,
- /* 35 */ 0xFF20, 11,
- /* 36 */ 0xFF40, 11,
- /* 37 */ 0xFF50, 12,
- /* 38 */ 0xFF60, 12,
- /* 39 */ 0xFF70, 12,
- /* 40 */ 0xFF80, 12,
- /* 41 */ 0xFF84, 14,
- /* 42 */ 0xFF86, 15,
- /* 43 */ 0xFF88, 15,
- /* 44 */ 0xFFFF, 16,
-};
-
-//[100]=========================
-static const unsigned char tbl100Y[64] = {
- 2, 1, 1, 2, 3, 5, 6, 7, 1, 1, 1, 2, 3, 7, 7, 6,
- 1, 1, 2, 3, 5, 7, 8, 7, 1, 2, 2, 3, 6, 10, 10, 7,
- 2, 2, 4, 7, 8, 13, 12, 9, 3, 4, 6, 8, 10, 13, 14, 11,
- 6, 8, 9, 10, 12, 15, 15, 12, 9, 11, 11, 12, 14, 12, 12, 12};
-static const unsigned char tbl100Uv[64] = {
- 3, 3, 4, 8, 18, 18, 18, 18, 3, 3, 4, 12, 18, 18, 18, 18,
- 4, 4, 10, 18, 18, 18, 18, 18, 8, 12, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18};
-
-//[086]=========================
-static const unsigned char tbl086Y[64] = {
- 3, 2, 1, 3, 4, 7, 9, 11, 2, 2, 2, 3, 4, 10, 11, 10,
- 2, 2, 3, 4, 7, 10, 12, 10, 2, 3, 4, 5, 9, 16, 15, 11,
- 3, 4, 6, 10, 12, 20, 19, 14, 4, 6, 10, 12, 15, 19, 21, 17,
- 9, 12, 14, 16, 19, 22, 22, 18, 13, 17, 17, 18, 21, 18, 19, 18};
-static const unsigned char tbl086Uv[64] = {
- 4, 5, 6, 13, 27, 27, 27, 27, 5, 5, 7, 18, 27, 27, 27, 27,
- 6, 7, 15, 27, 27, 27, 27, 27, 13, 18, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27};
-
-//[071]=========================
-static const unsigned char tbl071Y[64] = {
- 6, 4, 3, 6, 9, 15, 19, 22, 4, 4, 5, 7, 9, 21, 22, 20,
- 5, 4, 6, 9, 15, 21, 25, 21, 5, 6, 8, 10, 19, 32, 30, 23,
- 6, 8, 13, 21, 25, 40, 38, 28, 9, 13, 20, 24, 30, 39, 42, 34,
- 18, 24, 29, 32, 38, 45, 45, 37, 27, 34, 35, 36, 42, 37, 38, 37};
-static const unsigned char tbl071Uv[64] = {
- 9, 10, 13, 26, 55, 55, 55, 55, 10, 11, 14, 37, 55, 55, 55, 55,
- 13, 14, 31, 55, 55, 55, 55, 55, 26, 37, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55};
-//[057]=========================
-static const unsigned char tbl057Y[64] = {
- 9, 6, 5, 9, 13, 22, 28, 34, 6, 6, 7, 10, 14, 32, 33, 30,
- 7, 7, 9, 13, 22, 32, 38, 31, 7, 9, 12, 16, 28, 48, 45, 34,
- 10, 12, 20, 31, 38, 61, 57, 43, 13, 19, 30, 36, 45, 58, 63, 51,
- 27, 36, 43, 48, 57, 68, 67, 56, 40, 51, 53, 55, 63, 56, 57, 55};
-static const unsigned char tbl057Uv[64] = {
- 13, 14, 19, 38, 80, 80, 80, 80, 14, 17, 21, 53, 80, 80, 80, 80,
- 19, 21, 45, 80, 80, 80, 80, 80, 38, 53, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80};
-
-//[043]=========================
-static const unsigned char tbl043Y[64] = {
- 11, 7, 7, 11, 17, 28, 36, 43, 8, 8, 10, 13, 18, 41, 43, 39,
- 10, 9, 11, 17, 28, 40, 49, 40, 10, 12, 15, 20, 36, 62, 57, 44,
- 12, 15, 26, 40, 48, 78, 74, 55, 17, 25, 39, 46, 58, 74, 81, 66,
- 35, 46, 56, 62, 74, 86, 86, 72, 51, 66, 68, 70, 80, 71, 74, 71};
-static const unsigned char tbl043Uv[64] = {
- 18, 19, 26, 51, 108, 108, 108, 108, 19, 22, 28, 72, 108,
- 108, 108, 108, 26, 28, 61, 108, 108, 108, 108, 108, 51, 72,
- 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
- 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
- 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108};
-
-//[029]=========================
-static const unsigned char tbl029Y[64] = {
- 14, 9, 9, 14, 21, 36, 46, 55, 10, 10, 12, 17, 23, 52, 54, 49,
- 12, 11, 14, 21, 36, 51, 62, 50, 12, 15, 19, 26, 46, 78, 72, 56,
- 16, 19, 33, 50, 61, 98, 93, 69, 21, 31, 49, 58, 73, 94, 102, 83,
- 44, 58, 70, 78, 93, 109, 108, 91, 65, 83, 86, 88, 101, 90, 93, 89};
-static const unsigned char tbl029Uv[64] = {
- 22, 24, 32, 63, 133, 133, 133, 133, 24, 28, 34, 88, 133,
- 133, 133, 133, 32, 34, 75, 133, 133, 133, 133, 133, 63, 88,
- 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
- 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133,
- 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, 133};
-
-//[014]=========================
-static const unsigned char tbl014Y[64] = {
- 17, 12, 10, 17, 26, 43, 55, 66, 13, 13, 15, 20, 28, 63, 65, 60,
- 15, 14, 17, 26, 43, 62, 75, 61, 15, 18, 24, 31, 55, 95, 87, 67,
- 19, 24, 40, 61, 74, 119, 112, 84, 26, 38, 60, 70, 88, 113, 123, 100,
- 53, 70, 85, 95, 112, 132, 131, 110, 78, 100, 103, 107, 122, 109, 112, 108};
-static const unsigned char tbl014Uv[64] = {
- 27, 29, 39, 76, 160, 160, 160, 160, 29, 34, 42, 107, 160,
- 160, 160, 160, 39, 42, 91, 160, 160, 160, 160, 160, 76, 107,
- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
- 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160};
-//[000]=========================
-static const unsigned char tbl000Y[64] = {
- 20, 13, 12, 20, 30, 50, 63, 76, 15, 15, 17, 23, 32, 72, 75, 68,
- 17, 16, 20, 30, 50, 71, 86, 70, 17, 21, 27, 36, 63, 108, 100, 77,
- 22, 27, 46, 70, 85, 136, 128, 96, 30, 43, 68, 80, 101, 130, 141, 115,
- 61, 80, 97, 108, 128, 151, 150, 126, 90, 115, 118, 122, 140, 125, 128, 123};
-static const unsigned char tbl000Uv[64] = {
- 31, 33, 45, 88, 185, 185, 185, 185, 33, 39, 48, 123, 185,
- 185, 185, 185, 45, 48, 105, 185, 185, 185, 185, 185, 88, 123,
- 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
- 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185,
- 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185};
-
-struct HuffmanTable {
- unsigned char length[17]; // k =1-16 ; L[k] indicates the number of Huffman
- // codes of length k
- unsigned short int minorCode[17]; // indicates the value of the smallest
- // Huffman code of length k
- unsigned short int majorCode[17]; // similar, but the highest code
- unsigned char v[65536]; // V[k][j] = Value associated to the j-th Huffman
- // code of length k
- // High nibble = nr of previous 0 coefficients
- // Low nibble = size (in bits) of the coefficient which will be taken from the
- // data stream
- unsigned char len[65536];
-};
diff --git a/include/ast_jpeg_decoder.hpp b/include/ast_jpeg_decoder.hpp deleted file mode 100644 index e8bdddbf59..0000000000 --- a/include/ast_jpeg_decoder.hpp +++ /dev/null @@ -1,1547 +0,0 @@ -#pragma once - -#include <aspeed/JTABLES.H> - -#include <array> -#include <ast_video_types.hpp> -#include <cassert> -#include <cstdint> -#include <cstring> -#include <iostream> -#include <vector> - -namespace ast_video -{ - -struct ColorCache -{ - ColorCache() : - color{0x008080, 0xFF8080, 0x808080, 0xC08080}, index{0, 1, 2, 3} - { - } - - unsigned long color[4]; - unsigned char index[4]; - unsigned char bitMapBits{}; -}; - -struct RGB -{ - unsigned char b; - unsigned char g; - unsigned char r; - unsigned char reserved; -}; - -enum class JpgBlock -{ - JPEG_NO_SKIP_CODE = 0x00, - JPEG_SKIP_CODE = 0x08, - - JPEG_PASS2_CODE = 0x02, - JPEG_SKIP_PASS2_CODE = 0x0A, - - LOW_JPEG_NO_SKIP_CODE = 0x04, - LOW_JPEG_SKIP_CODE = 0x0C, - - VQ_NO_SKIP_1_COLOR_CODE = 0x05, - VQ_SKIP_1_COLOR_CODE = 0x0D, - - VQ_NO_SKIP_2_COLOR_CODE = 0x06, - VQ_SKIP_2_COLOR_CODE = 0x0E, - - VQ_NO_SKIP_4_COLOR_CODE = 0x07, - VQ_SKIP_4_COLOR_CODE = 0x0F, - - FRAME_END_CODE = 0x09, - -}; - -class AstJpegDecoder -{ - public: - AstJpegDecoder() - { - // TODO(ed) figure out how to init this in the constructor - yuvBuffer.resize(1920 * 1200); - outBuffer.resize(1920 * 1200); - for (auto &r : outBuffer) - { - r.r = 0x00; - r.g = 0x00; - r.b = 0x00; - r.reserved = 0xAA; - } - - int qfactor = 16; - - scalefactor = qfactor; - scalefactoruv = qfactor; - advancescalefactor = 16; - advancescalefactoruv = 16; - initJpgTable(); - } - - void loadQuantTable(std::array<long, 64> &quant_table) - { - float scalefactorF[8] = {1.0f, 1.387039845f, 1.306562965f, - 1.175875602f, 1.0f, 0.785694958f, - 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder - // from zig-zag order - switch (ySelector) - { - case 0: - stdLuminanceQt = tbl000Y; - break; - case 1: - stdLuminanceQt = tbl014Y; - break; - case 2: - stdLuminanceQt = tbl029Y; - break; - case 3: - stdLuminanceQt = tbl043Y; - break; - case 4: - stdLuminanceQt = tbl057Y; - break; - case 5: - stdLuminanceQt = tbl071Y; - break; - case 6: - stdLuminanceQt = tbl086Y; - break; - case 7: - stdLuminanceQt = tbl100Y; - break; - } - setQuantTable(stdLuminanceQt, static_cast<uint8_t>(scalefactor), - tempQT); - - for (j = 0; j <= 63; j++) - { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) - { - for (col = 0; col <= 7; col++) - { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactorF[row] * scalefactorF[col]) * - 65536); - j++; - } - } - bytePos += 64; - } - - void loadQuantTableCb(std::array<long, 64> &quant_table) - { - float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder from zig-zag order - if (mapping == 0) - { - switch (uvSelector) - { - case 0: - stdChrominanceQt = tbl000Y; - break; - case 1: - stdChrominanceQt = tbl014Y; - break; - case 2: - stdChrominanceQt = tbl029Y; - break; - case 3: - stdChrominanceQt = tbl043Y; - break; - case 4: - stdChrominanceQt = tbl057Y; - break; - case 5: - stdChrominanceQt = tbl071Y; - break; - case 6: - stdChrominanceQt = tbl086Y; - break; - case 7: - stdChrominanceQt = tbl100Y; - break; - } - } - else - { - switch (uvSelector) - { - case 0: - stdChrominanceQt = tbl000Uv; - break; - case 1: - stdChrominanceQt = tbl014Uv; - break; - case 2: - stdChrominanceQt = tbl029Uv; - break; - case 3: - stdChrominanceQt = tbl043Uv; - break; - case 4: - stdChrominanceQt = tbl057Uv; - break; - case 5: - stdChrominanceQt = tbl071Uv; - break; - case 6: - stdChrominanceQt = tbl086Uv; - break; - case 7: - stdChrominanceQt = tbl100Uv; - break; - } - } - setQuantTable(stdChrominanceQt, static_cast<uint8_t>(scalefactoruv), - tempQT); - - for (j = 0; j <= 63; j++) - { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) - { - for (col = 0; col <= 7; col++) - { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactor[row] * scalefactor[col]) * - 65536); - j++; - } - } - bytePos += 64; - } - // Note: Added for Dual_JPEG - void loadAdvanceQuantTable(std::array<long, 64> &quant_table) - { - float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder - // from zig-zag order - switch (advanceSelector) - { - case 0: - stdLuminanceQt = tbl000Y; - break; - case 1: - stdLuminanceQt = tbl014Y; - break; - case 2: - stdLuminanceQt = tbl029Y; - break; - case 3: - stdLuminanceQt = tbl043Y; - break; - case 4: - stdLuminanceQt = tbl057Y; - break; - case 5: - stdLuminanceQt = tbl071Y; - break; - case 6: - stdLuminanceQt = tbl086Y; - break; - case 7: - stdLuminanceQt = tbl100Y; - break; - } - // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG - setQuantTable(stdLuminanceQt, static_cast<uint8_t>(advancescalefactor), - tempQT); - - for (j = 0; j <= 63; j++) - { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) - { - for (col = 0; col <= 7; col++) - { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactor[row] * scalefactor[col]) * - 65536); - j++; - } - } - bytePos += 64; - } - - // Note: Added for Dual-JPEG - void loadAdvanceQuantTableCb(std::array<long, 64> &quant_table) - { - float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f, - 1.0f, 0.785694958f, 0.541196100f, 0.275899379f}; - uint8_t j, row, col; - std::array<uint8_t, 64> tempQT{}; - - // Load quantization coefficients from JPG file, scale them for DCT and - // reorder - // from zig-zag order - if (mapping == 1) - { - switch (advanceSelector) - { - case 0: - stdChrominanceQt = tbl000Y; - break; - case 1: - stdChrominanceQt = tbl014Y; - break; - case 2: - stdChrominanceQt = tbl029Y; - break; - case 3: - stdChrominanceQt = tbl043Y; - break; - case 4: - stdChrominanceQt = tbl057Y; - break; - case 5: - stdChrominanceQt = tbl071Y; - break; - case 6: - stdChrominanceQt = tbl086Y; - break; - case 7: - stdChrominanceQt = tbl100Y; - break; - } - } - else - { - switch (advanceSelector) - { - case 0: - stdChrominanceQt = tbl000Uv; - break; - case 1: - stdChrominanceQt = tbl014Uv; - break; - case 2: - stdChrominanceQt = tbl029Uv; - break; - case 3: - stdChrominanceQt = tbl043Uv; - break; - case 4: - stdChrominanceQt = tbl057Uv; - break; - case 5: - stdChrominanceQt = tbl071Uv; - break; - case 6: - stdChrominanceQt = tbl086Uv; - break; - case 7: - stdChrominanceQt = tbl100Uv; - break; - } - } - // Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG - setQuantTable(stdChrominanceQt, - static_cast<uint8_t>(advancescalefactoruv), tempQT); - - for (j = 0; j <= 63; j++) - { - quant_table[j] = tempQT[zigzag[j]]; - } - j = 0; - for (row = 0; row <= 7; row++) - { - for (col = 0; col <= 7; col++) - { - quant_table[j] = static_cast<long>( - (quant_table[j] * scalefactor[row] * scalefactor[col]) * - 65536); - j++; - } - } - bytePos += 64; - } - - void idctTransform(short *coef, uint8_t *data, uint8_t nBlock) - { -#define FIX_1_082392200 ((int)277) /* FIX(1.082392200) */ -#define FIX_1_414213562 ((int)362) /* FIX(1.414213562) */ -#define FIX_1_847759065 ((int)473) /* FIX(1.847759065) */ -#define FIX_2_613125930 ((int)669) /* FIX(2.613125930) */ - -#define MULTIPLY(var, cons) ((int)((var) * (cons)) >> 8) - - int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - int tmp10, tmp11, tmp12, tmp13; - int z5, z10, z11, z12, z13; - int workspace[64]; /* buffers data between passes */ - - short *inptr = coef; - long *quantptr; - int *wsptr = workspace; - unsigned char *outptr; - unsigned char *rLimit = rlimitTable + 128; - int ctr, dcval, dctsize = 8; - - quantptr = &qt[nBlock][0]; - - // Pass 1: process columns from input (inptr), store into work - // array(wsptr) - - for (ctr = 8; ctr > 0; ctr--) - { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit - * this by short-circuiting the IDCT calculation for any column in - * which all the AC terms are zero. In that case each output is - * equal to the DC coefficient (with scale factor as needed). With - * typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if ((inptr[dctsize * 1] | inptr[dctsize * 2] | inptr[dctsize * 3] | - inptr[dctsize * 4] | inptr[dctsize * 5] | inptr[dctsize * 6] | - inptr[dctsize * 7]) == 0) - { - /* AC terms all zero */ - dcval = static_cast<int>( - (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16); - - wsptr[dctsize * 0] = dcval; - wsptr[dctsize * 1] = dcval; - wsptr[dctsize * 2] = dcval; - wsptr[dctsize * 3] = dcval; - wsptr[dctsize * 4] = dcval; - wsptr[dctsize * 5] = dcval; - wsptr[dctsize * 6] = dcval; - wsptr[dctsize * 7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16; - tmp1 = (inptr[dctsize * 2] * quantptr[dctsize * 2]) >> 16; - tmp2 = (inptr[dctsize * 4] * quantptr[dctsize * 4]) >> 16; - tmp3 = (inptr[dctsize * 6] * quantptr[dctsize * 6]) >> 16; - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = (inptr[dctsize * 1] * quantptr[dctsize * 1]) >> 16; - tmp5 = (inptr[dctsize * 3] * quantptr[dctsize * 3]) >> 16; - tmp6 = (inptr[dctsize * 5] * quantptr[dctsize * 5]) >> 16; - tmp7 = (inptr[dctsize * 7] * quantptr[dctsize * 7]) >> 16; - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[dctsize * 0] = (tmp0 + tmp7); - wsptr[dctsize * 7] = (tmp0 - tmp7); - wsptr[dctsize * 1] = (tmp1 + tmp6); - wsptr[dctsize * 6] = (tmp1 - tmp6); - wsptr[dctsize * 2] = (tmp2 + tmp5); - wsptr[dctsize * 5] = (tmp2 - tmp5); - wsptr[dctsize * 4] = (tmp3 + tmp4); - wsptr[dctsize * 3] = (tmp3 - tmp4); - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - -/* Pass 2: process rows from work array, store into output array. */ -/* Note that we must descale the results by a factor of 8 == 2**3, */ -/* and also undo the PASS1_BITS scaling. */ - -//#define RANGE_MASK 1023; //2 bits wider than legal samples -#define PASS1_BITS 0 -#define IDESCALE(x, n) ((int)((x) >> (n))) - - wsptr = workspace; - for (ctr = 0; ctr < dctsize; ctr++) - { - outptr = data + ctr * 8; - - /* Rows of zeroes can be exploited in the same way as we did with - * columns. However, the column calculation has created many nonzero - * AC terms, so the simplification applies less often (typically 5% - * to 10% of the time). On machines with very fast multiplication, - * it's possible that the test takes more time than it's worth. In - * that case this section may be commented out. - */ - /* Even part */ - - tmp10 = (wsptr[0] + wsptr[4]); - tmp11 = (wsptr[0] - wsptr[4]); - - tmp13 = (wsptr[2] + wsptr[6]); - tmp12 = MULTIPLY((int)wsptr[2] - (int)wsptr[6], FIX_1_414213562) - - tmp13; - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */ - - z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */ - tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */ - tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit - */ - - outptr[0] = - rLimit[IDESCALE((tmp0 + tmp7), (PASS1_BITS + 3)) & 1023L]; - outptr[7] = - rLimit[IDESCALE((tmp0 - tmp7), (PASS1_BITS + 3)) & 1023L]; - outptr[1] = - rLimit[IDESCALE((tmp1 + tmp6), (PASS1_BITS + 3)) & 1023L]; - outptr[6] = - rLimit[IDESCALE((tmp1 - tmp6), (PASS1_BITS + 3)) & 1023L]; - outptr[2] = - rLimit[IDESCALE((tmp2 + tmp5), (PASS1_BITS + 3)) & 1023L]; - outptr[5] = - rLimit[IDESCALE((tmp2 - tmp5), (PASS1_BITS + 3)) & 1023L]; - outptr[4] = - rLimit[IDESCALE((tmp3 + tmp4), (PASS1_BITS + 3)) & 1023L]; - outptr[3] = - rLimit[IDESCALE((tmp3 - tmp4), (PASS1_BITS + 3)) & 1023L]; - - wsptr += dctsize; /* advance pointer to next row */ - } - } - void yuvToRgb( - int txb, int tyb, - unsigned char - *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes - struct RGB *pYUV, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes - unsigned char - *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes - ) - { - int i, j, pos, m, n; - unsigned char cb, cr, *py, *pcb, *pcr, *py420[4]; - int y; - struct RGB *pByte; - int nBlocksInMcu = 6; - unsigned int pixelX, pixelY; - - pByte = reinterpret_cast<struct RGB *>(pBgr); - if (yuvmode == YuvMode::YUV444) - { - py = pYCbCr; - pcb = pYCbCr + 64; - pcr = pcb + 64; - - pixelX = txb * 8; - pixelY = tyb * 8; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 8; j++) - { - for (i = 0; i < 8; i++) - { - m = ((j << 3) + i); - y = py[m]; - cb = pcb[m]; - cr = pcr[m]; - n = pos + i; - // For 2Pass. Save the YUV value - pYUV[n].b = cb; - pYUV[n].g = y; - pYUV[n].r = cr; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; - } - pos += width; - } - } - else - { - for (i = 0; i < nBlocksInMcu - 2; i++) - { - py420[i] = pYCbCr + i * 64; - } - pcb = pYCbCr + (nBlocksInMcu - 2) * 64; - pcr = pcb + 64; - - pixelX = txb * 16; - pixelY = tyb * 16; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 16; j++) - { - for (i = 0; i < 16; i++) - { - // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3} - y = *(py420[(j >> 3) * 2 + (i >> 3)]++); - m = ((j >> 1) << 3) + (i >> 1); - cb = pcb[m]; - cr = pcr[m]; - n = pos + i; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; - } - pos += width; - } - } - } - void yuvToBuffer( - int txb, int tyb, - unsigned char - *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes - struct RGB - *pYUV, // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes - unsigned char - *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes - ) - { - int i, j, pos, m, n; - unsigned char cb, cr, *py, *pcb, *pcr, *py420[4]; - int y; - struct RGB *pByte; - int nBlocksInMcu = 6; - unsigned int pixelX, pixelY; - - pByte = reinterpret_cast<struct RGB *>(pBgr); - if (yuvmode == YuvMode::YUV444) - { - py = pYCbCr; - pcb = pYCbCr + 64; - pcr = pcb + 64; - - pixelX = txb * 8; - pixelY = tyb * 8; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 8; j++) - { - for (i = 0; i < 8; i++) - { - m = ((j << 3) + i); - n = pos + i; - y = pYUV[n].g + (py[m] - 128); - cb = pYUV[n].b + (pcb[m] - 128); - cr = pYUV[n].r + (pcr[m] - 128); - pYUV[n].b = cb; - pYUV[n].g = y; - pYUV[n].r = cr; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; - } - pos += width; - } - } - else - { - for (i = 0; i < nBlocksInMcu - 2; i++) - { - py420[i] = pYCbCr + i * 64; - } - pcb = pYCbCr + (nBlocksInMcu - 2) * 64; - pcr = pcb + 64; - - pixelX = txb * 16; - pixelY = tyb * 16; - pos = (pixelY * width) + pixelX; - - for (j = 0; j < 16; j++) - { - for (i = 0; i < 16; i++) - { - // block number is ((j/8) * 2 + i/8)={0, 1, 2, 3} - y = *(py420[(j >> 3) * 2 + (i >> 3)]++); - m = ((j >> 1) << 3) + (i >> 1); - cb = pcb[m]; - cr = pcr[m]; - n = pos + i; - pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]]; - pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]]; - pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]]; - } - pos += width; - } - } - } - void decompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection) - { - unsigned char *ptr; - unsigned char byTileYuv[768] = {}; - - memset(dctCoeff, 0, 384 * 2); - ptr = byTileYuv; - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0); - idctTransform(dctCoeff, ptr, QT_TableSelection); - ptr += 64; - - if (yuvmode == YuvMode::YUV420) - { - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 64); - idctTransform(dctCoeff + 64, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 128); - idctTransform(dctCoeff + 128, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 192); - idctTransform(dctCoeff + 192, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 256); - idctTransform(dctCoeff + 256, ptr, QT_TableSelection + 1); - ptr += 64; - - processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 320); - idctTransform(dctCoeff + 320, ptr, QT_TableSelection + 1); - } - else - { - processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64); - idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1); - ptr += 64; - - processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128); - idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1); - } - - // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); - // yuvBuffer for YUV record - yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(), - reinterpret_cast<unsigned char *>(outBuf)); - } - - void decompress2Pass(int txb, int tyb, char *outBuf, - uint8_t QT_TableSelection) - { - unsigned char *ptr; - unsigned char byTileYuv[768]; - memset(dctCoeff, 0, 384 * 2); - - ptr = byTileYuv; - processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0); - idctTransform(dctCoeff, ptr, QT_TableSelection); - ptr += 64; - - processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64); - idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1); - ptr += 64; - - processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128); - idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1); - - yuvToBuffer(txb, tyb, byTileYuv, yuvBuffer.data(), - reinterpret_cast<unsigned char *>(outBuf)); - // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); - } - - void vqDecompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection, - struct ColorCache *VQ) - { - unsigned char *ptr, i; - unsigned char byTileYuv[192]; - int data; - - ptr = byTileYuv; - if (VQ->bitMapBits == 0) - { - for (i = 0; i < 64; i++) - { - ptr[0] = (VQ->color[VQ->index[0]] & 0xFF0000) >> 16; - ptr[64] = (VQ->color[VQ->index[0]] & 0x00FF00) >> 8; - ptr[128] = VQ->color[VQ->index[0]] & 0x0000FF; - ptr += 1; - } - } - else - { - for (i = 0; i < 64; i++) - { - data = static_cast<int>(lookKbits(VQ->bitMapBits)); - ptr[0] = (VQ->color[VQ->index[data]] & 0xFF0000) >> 16; - ptr[64] = (VQ->color[VQ->index[data]] & 0x00FF00) >> 8; - ptr[128] = VQ->color[VQ->index[data]] & 0x0000FF; - ptr += 1; - skipKbits(VQ->bitMapBits); - } - } - // yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf); - yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(), - reinterpret_cast<unsigned char *>(outBuf)); - } - - void moveBlockIndex() - { - if (yuvmode == YuvMode::YUV444) - { - txb++; - if (txb >= static_cast<int>(width / 8)) - { - tyb++; - if (tyb >= static_cast<int>(height / 8)) - { - tyb = 0; - } - txb = 0; - } - } - else - { - txb++; - if (txb >= static_cast<int>(width / 16)) - { - tyb++; - if (tyb >= static_cast<int>(height / 16)) - { - tyb = 0; - } - txb = 0; - } - } - } - - void initColorTable() - { - int i, x; - int nScale = 1L << 16; // equal to power(2,16) - int nHalf = nScale >> 1; - -#define FIX(x) ((int)((x)*nScale + 0.5)) - - /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ - /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ - /* Cr=>r value is nearest int to 1.597656 * x */ - /* Cb=>b value is nearest int to 2.015625 * x */ - /* Cr=>g value is scaled-up -0.8125 * x */ - /* Cb=>g value is scaled-up -0.390625 * x */ - for (i = 0, x = -128; i < 256; i++, x++) - { - mCrToR[i] = (FIX(1.597656) * x + nHalf) >> 16; - mCbToB[i] = (FIX(2.015625) * x + nHalf) >> 16; - mCrToG[i] = (-FIX(0.8125) * x + nHalf) >> 16; - mCbToG[i] = (-FIX(0.390625) * x + nHalf) >> 16; - } - for (i = 0, x = -16; i < 256; i++, x++) - { - mY[i] = (FIX(1.164) * x + nHalf) >> 16; - } - // For color Text Enchance Y Re-map. Recommend to disable in default - /* - for (i = 0; i < - (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i++) { temp = - (double)i / VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate; temp1 - = 1.0 / VideoEngineInfo->INFData.Gamma1Parameter; mY[i] = - (BYTE)(VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate * pow (temp, - temp1)); - if (mY[i] > 255) mY[i] = 255; - } - for (i = (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i < - 256; i++) { mY[i] = - (BYTE)((VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) + (256 - - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) * ( pow((double)((i - - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) / (256 - - (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate))), (1.0 / - VideoEngineInfo->INFData.Gamma2Parameter)) )); - if (mY[i] > 255) mY[i] = 255; - } - */ - } - void loadHuffmanTable(HuffmanTable *HT, const unsigned char *nrcode, - const unsigned char *value, - const unsigned short int *Huff_code) - { - unsigned char k, j, i; - unsigned int code, codeIndex; - - for (j = 1; j <= 16; j++) - { - HT->length[j] = nrcode[j]; - } - for (i = 0, k = 1; k <= 16; k++) - { - for (j = 0; j < HT->length[k]; j++) - { - HT->v[wordHiLo(k, j)] = value[i]; - i++; - } - } - - code = 0; - for (k = 1; k <= 16; k++) - { - HT->minorCode[k] = static_cast<unsigned short int>(code); - for (j = 1; j <= HT->length[k]; j++) - { - code++; - } - HT->majorCode[k] = static_cast<unsigned short int>(code - 1); - code *= 2; - if (HT->length[k] == 0) - { - HT->minorCode[k] = 0xFFFF; - HT->majorCode[k] = 0; - } - } - - HT->len[0] = 2; - i = 2; - - for (codeIndex = 1; codeIndex < 65535; codeIndex++) - { - if (codeIndex < Huff_code[i]) - { - HT->len[codeIndex] = - static_cast<unsigned char>(Huff_code[i + 1]); - } - else - { - i = i + 2; - HT->len[codeIndex] = - static_cast<unsigned char>(Huff_code[i + 1]); - } - } - } - void initJpgTable() - { - initColorTable(); - prepareRangeLimitTable(); - loadHuffmanTable(&htdc[0], stdDcLuminanceNrcodes, stdDcLuminanceValues, - dcLuminanceHuffmancode); - loadHuffmanTable(&htac[0], stdAcLuminanceNrcodes, stdAcLuminanceValues, - acLuminanceHuffmancode); - loadHuffmanTable(&htdc[1], stdDcChrominanceNrcodes, - stdDcChrominanceValues, dcChrominanceHuffmancode); - loadHuffmanTable(&htac[1], stdAcChrominanceNrcodes, - stdAcChrominanceValues, acChrominanceHuffmancode); - } - - void prepareRangeLimitTable() - /* Allocate and fill in the sample_range_limit table */ - { - int j; - rlimitTable = reinterpret_cast<unsigned char *>(malloc(5 * 256L + 128)); - /* First segment of "simple" table: limit[x] = 0 for x < 0 */ - memset((void *)rlimitTable, 0, 256); - rlimitTable += 256; /* allow negative subscripts of simple table */ - /* Main part of "simple" table: limit[x] = x */ - for (j = 0; j < 256; j++) - { - rlimitTable[j] = j; - } - /* End of simple table, rest of first half of post-IDCT table */ - for (j = 256; j < 640; j++) - { - rlimitTable[j] = 255; - } - - /* Second half of post-IDCT table */ - memset((void *)(rlimitTable + 640), 0, 384); - for (j = 0; j < 128; j++) - { - rlimitTable[j + 1024] = j; - } - } - - inline unsigned short int wordHiLo(uint8_t byte_high, uint8_t byte_low) - { - return (byte_high << 8) + byte_low; - } - - // river - void processHuffmanDataUnit(uint8_t DC_nr, uint8_t AC_nr, - signed short int *previous_DC, - unsigned short int position) - { - uint8_t nr = 0; - uint8_t k; - unsigned short int tmpHcode; - uint8_t sizeVal, count0; - unsigned short int *minCode; - uint8_t *huffValues; - uint8_t byteTemp; - - minCode = htdc[DC_nr].minorCode; - // maj_code=htdc[DC_nr].majorCode; - huffValues = htdc[DC_nr].v; - - // DC - k = htdc[DC_nr].len[static_cast<unsigned short int>(codebuf >> 16)]; - // river - // tmp_Hcode=lookKbits(k); - tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k)); - skipKbits(k); - sizeVal = huffValues[wordHiLo( - k, static_cast<uint8_t>(tmpHcode - minCode[k]))]; - if (sizeVal == 0) - { - dctCoeff[position + 0] = *previous_DC; - } - else - { - dctCoeff[position + 0] = *previous_DC + getKbits(sizeVal); - *previous_DC = dctCoeff[position + 0]; - } - - // Second, AC coefficient decoding - minCode = htac[AC_nr].minorCode; - // maj_code=htac[AC_nr].majorCode; - huffValues = htac[AC_nr].v; - - nr = 1; // AC coefficient - do - { - k = htac[AC_nr].len[static_cast<unsigned short int>(codebuf >> 16)]; - tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k)); - skipKbits(k); - - byteTemp = huffValues[wordHiLo( - k, static_cast<uint8_t>(tmpHcode - minCode[k]))]; - sizeVal = byteTemp & 0xF; - count0 = byteTemp >> 4; - if (sizeVal == 0) - { - if (count0 != 0xF) - { - break; - } - nr += 16; - } - else - { - nr += count0; // skip count_0 zeroes - dctCoeff[position + dezigzag[nr++]] = getKbits(sizeVal); - } - } while (nr < 64); - } - - unsigned short int lookKbits(uint8_t k) - { - unsigned short int revcode; - - revcode = static_cast<unsigned short int>(codebuf >> (32 - k)); - - return (revcode); - } - - void skipKbits(uint8_t k) - { - unsigned long readbuf; - - if ((newbits - k) <= 0) - { - readbuf = buffer[bufferIndex]; - bufferIndex++; - codebuf = (codebuf << k) | - ((newbuf | (readbuf >> (newbits))) >> (32 - k)); - newbuf = readbuf << (k - newbits); - newbits = 32 + newbits - k; - } - else - { - codebuf = (codebuf << k) | (newbuf >> (32 - k)); - newbuf = newbuf << k; - newbits -= k; - } - } - - signed short int getKbits(uint8_t k) - { - signed short int signedWordvalue; - - // river - // signed_wordvalue=lookKbits(k); - signedWordvalue = static_cast<unsigned short int>(codebuf >> (32 - k)); - if (((1L << (k - 1)) & signedWordvalue) == 0) - { - // neg_pow2 was previously defined as the below. It seemed silly to - // keep a table of values around for something THat's relatively - // easy to compute, so it was replaced with the appropriate math - // signed_wordvalue = signed_wordvalue - (0xFFFF >> (16 - k)); - std::array<signed short int, 17> negPow2 = { - 0, -1, -3, -7, -15, -31, -63, -127, - -255, -511, -1023, -2047, -4095, -8191, -16383, -32767}; - - signedWordvalue = signedWordvalue + negPow2[k]; - } - skipKbits(k); - return signedWordvalue; - } - int initJpgDecoding() - { - bytePos = 0; - loadQuantTable(qt[0]); - loadQuantTableCb(qt[1]); - // Note: Added for Dual-JPEG - loadAdvanceQuantTable(qt[2]); - loadAdvanceQuantTableCb(qt[3]); - return 1; - } - - void setQuantTable(const uint8_t *basic_table, uint8_t scale_factor, - std::array<uint8_t, 64> &newtable) - // Set quantization table and zigzag reorder it - { - uint8_t i; - long temp; - for (i = 0; i < 64; i++) - { - temp = (static_cast<long>(basic_table[i] * 16) / scale_factor); - /* limit the values to the valid range */ - if (temp <= 0L) - { - temp = 1L; - } - if (temp > 255L) - { - temp = 255L; /* limit to baseline range if requested */ - } - newtable[zigzag[i]] = static_cast<uint8_t>(temp); - } - } - - void updatereadbuf(uint32_t *codebuf, uint32_t *newbuf, int walks, - int *newbits, std::vector<uint32_t> &buffer) - { - unsigned long readbuf; - - if ((*newbits - walks) <= 0) - { - readbuf = buffer[bufferIndex]; - bufferIndex++; - *codebuf = (*codebuf << walks) | - ((*newbuf | (readbuf >> (*newbits))) >> (32 - walks)); - *newbuf = readbuf << (walks - *newbits); - *newbits = 32 + *newbits - walks; - } - else - { - *codebuf = (*codebuf << walks) | (*newbuf >> (32 - walks)); - *newbuf = *newbuf << walks; - *newbits -= walks; - } - } - - uint32_t decode(std::vector<uint32_t> &bufferVector, unsigned long width, - unsigned long height, YuvMode yuvmode_in, int ySelector, - int uvSelector) - { - ColorCache decodeColor; - if (width != userWidth || height != userHeight || - yuvmode_in != yuvmode || ySelector != ySelector || - uvSelector != uvSelector) - { - yuvmode = yuvmode_in; - ySelector = ySelector; // 0-7 - uvSelector = uvSelector; // 0-7 - userHeight = height; - userWidth = width; - width = width; - height = height; - - // TODO(ed) Magic number section. Document appropriately - advanceSelector = 0; // 0-7 - mapping = 0; // 0 or 1 - - if (yuvmode == YuvMode::YUV420) - { - if ((width % 16) != 0u) - { - width = width + 16 - (width % 16); - } - if ((height % 16) != 0u) - { - height = height + 16 - (height % 16); - } - } - else - { - if ((width % 8) != 0u) - { - width = width + 8 - (width % 8); - } - if ((height % 8) != 0u) - { - height = height + 8 - (height % 8); - } - } - - initJpgDecoding(); - } - // TODO(ed) cleanup cruft - buffer = bufferVector.data(); - - codebuf = bufferVector[0]; - newbuf = bufferVector[1]; - bufferIndex = 2; - - txb = tyb = 0; - newbits = 32; - dcy = dcCb = dcCr = 0; - - static const uint32_t vqHeaderMask = 0x01; - static const uint32_t vqNoUpdateHeader = 0x00; - static const uint32_t vqUpdateHeader = 0x01; - static const int vqNoUpdateLength = 0x03; - static const int vqUpdateLength = 0x1B; - static const uint32_t vqIndexMask = 0x03; - static const uint32_t vqColorMask = 0xFFFFFF; - - static const int blockAsT2100StartLength = 0x04; - static const int blockAsT2100SkipLength = 20; // S:1 H:3 X:8 Y:8 - - do - { - auto blockHeader = static_cast<JpgBlock>((codebuf >> 28) & 0xFF); - switch (blockHeader) - { - case JpgBlock::JPEG_NO_SKIP_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, - &newbits, bufferVector); - decompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0); - break; - case JpgBlock::FRAME_END_CODE: - return 0; - break; - case JpgBlock::JPEG_SKIP_CODE: - - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, - &newbits, bufferVector); - decompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0); - break; - case JpgBlock::VQ_NO_SKIP_1_COLOR_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, - &newbits, bufferVector); - decodeColor.bitMapBits = 0; - - for (int i = 0; i < 1; i++) - { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == - vqNoUpdateHeader) - { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, - &newbits, bufferVector); - } - else - { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, - &newbits, bufferVector); - } - } - vqDecompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - break; - case JpgBlock::VQ_SKIP_1_COLOR_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, - &newbits, bufferVector); - decodeColor.bitMapBits = 0; - - for (int i = 0; i < 1; i++) - { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == - vqNoUpdateHeader) - { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, - &newbits, bufferVector); - } - else - { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, - &newbits, bufferVector); - } - } - vqDecompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - break; - - case JpgBlock::VQ_NO_SKIP_2_COLOR_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, - &newbits, bufferVector); - decodeColor.bitMapBits = 1; - - for (int i = 0; i < 2; i++) - { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == - vqNoUpdateHeader) - { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, - &newbits, bufferVector); - } - else - { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, - &newbits, bufferVector); - } - } - vqDecompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - break; - case JpgBlock::VQ_SKIP_2_COLOR_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, - &newbits, bufferVector); - decodeColor.bitMapBits = 1; - - for (int i = 0; i < 2; i++) - { - decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == - vqNoUpdateHeader) - { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, - &newbits, bufferVector); - } - else - { - decodeColor.color[decodeColor.index[i]] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, - &newbits, bufferVector); - } - } - vqDecompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - - break; - case JpgBlock::VQ_NO_SKIP_4_COLOR_CODE: - updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, - &newbits, bufferVector); - decodeColor.bitMapBits = 2; - - for (unsigned char &i : decodeColor.index) - { - i = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == - vqNoUpdateHeader) - { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, - &newbits, bufferVector); - } - else - { - decodeColor.color[i] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, - &newbits, bufferVector); - } - } - vqDecompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - - break; - - case JpgBlock::VQ_SKIP_4_COLOR_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, - &newbits, bufferVector); - decodeColor.bitMapBits = 2; - - for (unsigned char &i : decodeColor.index) - { - i = ((codebuf >> 29) & vqIndexMask); - if (((codebuf >> 31) & vqHeaderMask) == - vqNoUpdateHeader) - { - updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, - &newbits, bufferVector); - } - else - { - decodeColor.color[i] = - ((codebuf >> 5) & vqColorMask); - updatereadbuf(&codebuf, &newbuf, vqUpdateLength, - &newbits, bufferVector); - } - } - vqDecompress(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), 0, - &decodeColor); - - break; - case JpgBlock::JPEG_SKIP_PASS2_CODE: - txb = (codebuf & 0x0FF00000) >> 20; - tyb = (codebuf & 0x0FF000) >> 12; - - updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, - &newbits, bufferVector); - decompress2Pass(txb, tyb, - reinterpret_cast<char *>(outBuffer.data()), - 2); - - break; - default: - // TODO(ed) propogate errors upstream - return -1; - break; - } - moveBlockIndex(); - - } while (bufferIndex <= bufferVector.size()); - - return -1; - } - -#ifdef cimg_version - void dump_to_bitmap_file() - { - cimg_library::CImg<unsigned char> image(width, height, 1, 3); - for (int y = 0; y < width; y++) - { - for (int x = 0; x < height; x++) - { - auto pixel = outBuffer[x + (y * width)]; - image(x, y, 0) = pixel.r; - image(x, y, 1) = pixel.g; - image(x, y, 2) = pixel.b; - } - } - image.save("/tmp/file2.bmp"); - } -#endif - - private: - YuvMode yuvmode{}; - // width and height are the modes your display used - unsigned long width{}; - unsigned long height{}; - unsigned long userWidth{}; - unsigned long userHeight{}; - unsigned char ySelector{}; - int scalefactor; - int scalefactoruv; - int advancescalefactor; - int advancescalefactoruv; - int mapping{}; - unsigned char uvSelector{}; - unsigned char advanceSelector{}; - int bytePos{}; // current byte position - - // quantization tables, no more than 4 quantization tables - std::array<std::array<long, 64>, 4> qt{}; - - // DC huffman tables , no more than 4 (0..3) - std::array<HuffmanTable, 4> htdc{}; - // AC huffman tables (0..3) - std::array<HuffmanTable, 4> htac{}; - std::array<int, 256> mCrToR{}; - std::array<int, 256> mCbToB{}; - std::array<int, 256> mCrToG{}; - std::array<int, 256> mCbToG{}; - std::array<int, 256> mY{}; - unsigned long bufferIndex{}; - uint32_t codebuf{}, newbuf{}, readbuf{}; - const unsigned char *stdLuminanceQt{}; - const uint8_t *stdChrominanceQt{}; - - signed short int dcy{}, dcCb{}, dcCr{}; // Coeficientii DC pentru Y,Cb,Cr - signed short int dctCoeff[384]{}; - // std::vector<signed short int> dctCoeff; // Current DCT_coefficients - // quantization table number for Y, Cb, Cr - uint8_t yqNr = 0, cbQNr = 1, crQNr = 1; - // DC Huffman table number for Y,Cb, Cr - uint8_t ydcNr = 0, cbDcNr = 1, crDcNr = 1; - // AC Huffman table number for Y,Cb, Cr - uint8_t yacNr = 0, cbAcNr = 1, crAcNr = 1; - int txb = 0; - int tyb = 0; - int newbits{}; - uint8_t *rlimitTable{}; - std::vector<RGB> yuvBuffer; - // TODO(ed) this shouldn't exist. It is cruft that needs cleaning up - uint32_t *buffer{}; - - public: - std::vector<RGB> outBuffer; -}; -} // namespace ast_video
\ No newline at end of file diff --git a/include/kvm_websocket.hpp b/include/kvm_websocket.hpp new file mode 100644 index 0000000000..aa2eaecc32 --- /dev/null +++ b/include/kvm_websocket.hpp @@ -0,0 +1,173 @@ +#pragma once +#include <crow/app.h> +#include <crow/websocket.h> +#include <sys/socket.h> + +#include <boost/container/flat_map.hpp> +#include <boost/container/flat_set.hpp> +#include <webserver_common.hpp> + +namespace crow +{ +namespace obmc_kvm +{ + +static std::unique_ptr<boost::asio::ip::tcp::socket> hostSocket; + +// TODO(ed) validate that these buffer sizes are sane +static boost::beast::flat_static_buffer<1024U * 50U> outputBuffer; +static boost::beast::flat_static_buffer<1024U> inputBuffer; + +static crow::websocket::Connection* session = nullptr; + +static bool doingWrite = false; + +inline void doWrite() +{ + if (doingWrite) + { + BMCWEB_LOG_DEBUG << "Already writing. Bailing out"; + return; + } + if (inputBuffer.size() == 0) + { + BMCWEB_LOG_DEBUG << "inputBuffer empty. Bailing out"; + return; + } + + doingWrite = true; + hostSocket->async_write_some( + inputBuffer.data(), + [](boost::beast::error_code ec, std::size_t bytes_written) { + BMCWEB_LOG_DEBUG << "Wrote " << bytes_written << "bytes"; + doingWrite = false; + inputBuffer.consume(bytes_written); + + if (session == nullptr) + { + return; + } + if (ec == boost::asio::error::eof) + { + session->close("KVM socket port closed"); + return; + } + if (ec) + { + session->close("Error in reading to host port"); + BMCWEB_LOG_ERROR << "Error in KVM socket write " << ec; + return; + } + doWrite(); + }); +} + +inline void doRead(); + +inline void readDone(const boost::system::error_code& ec, std::size_t bytesRead) +{ + outputBuffer.commit(bytesRead); + BMCWEB_LOG_DEBUG << "read done. Read " << bytesRead << " bytes"; + if (ec) + { + BMCWEB_LOG_ERROR << "Couldn't read from KVM socket port: " << ec; + if (session != nullptr) + { + session->close("Error in connecting to KVM port"); + } + return; + } + if (session == nullptr) + { + return; + } + + boost::beast::string_view payload( + static_cast<const char*>(outputBuffer.data().data()), bytesRead); + BMCWEB_LOG_DEBUG << "Sending payload size " << payload.size(); + session->sendBinary(payload); + outputBuffer.consume(bytesRead); + + doRead(); +} + +inline void doRead() +{ + std::size_t bytes = outputBuffer.capacity() - outputBuffer.size(); + BMCWEB_LOG_DEBUG << "Reading " << bytes << " from kvm socket"; + hostSocket->async_read_some( + outputBuffer.prepare(outputBuffer.capacity() - outputBuffer.size()), + readDone); +} + +inline void connectHandler(const boost::system::error_code& ec) +{ + if (ec) + { + BMCWEB_LOG_ERROR << "Couldn't connect to KVM socket port: " << ec; + if (session != nullptr) + { + session->close("Error in connecting to KVM port"); + } + return; + } + + doWrite(); + doRead(); +} + +inline void requestRoutes(CrowApp& app) +{ + BMCWEB_ROUTE(app, "/kvm/0") + .websocket() + .onopen([](crow::websocket::Connection& conn) { + BMCWEB_LOG_DEBUG << "Connection " << &conn << " opened"; + + if (session != nullptr) + { + conn.close("User already connected"); + return; + } + + session = &conn; + if (hostSocket == nullptr) + { + boost::asio::ip::tcp::endpoint endpoint( + boost::asio::ip::address::from_string("127.0.0.1"), 5900); + + hostSocket = std::make_unique<boost::asio::ip::tcp::socket>( + conn.get_io_context()); + hostSocket->async_connect(endpoint, connectHandler); + } + }) + .onclose( + [](crow::websocket::Connection& conn, const std::string& reason) { + session = nullptr; + hostSocket = nullptr; + inputBuffer.reset(); + outputBuffer.reset(); + }) + .onmessage([](crow::websocket::Connection& conn, + const std::string& data, bool is_binary) { + if (data.length() > inputBuffer.capacity()) + { + BMCWEB_LOG_ERROR << "Buffer overrun when writing " + << data.length() << " bytes"; + conn.close("Buffer overrun"); + return; + } + + BMCWEB_LOG_DEBUG << "Read " << data.size() + << " bytes from websocket"; + boost::asio::buffer_copy(inputBuffer.prepare(data.size()), + boost::asio::buffer(data)); + BMCWEB_LOG_DEBUG << "commiting " << data.size() + << " bytes from websocket"; + inputBuffer.commit(data.size()); + + BMCWEB_LOG_DEBUG << "inputbuffer size " << inputBuffer.size(); + doWrite(); + }); +} +} // namespace obmc_kvm +} // namespace crow diff --git a/include/security_headers_middleware.hpp b/include/security_headers_middleware.hpp index 5e8e7d9911..1ebc43ca7a 100644 --- a/include/security_headers_middleware.hpp +++ b/include/security_headers_middleware.hpp @@ -36,7 +36,12 @@ struct SecurityHeadersMiddleware res.addHeader(bf::pragma, "no-cache"); res.addHeader(bf::cache_control, "no-Store,no-Cache"); - res.addHeader("Content-Security-Policy", "default-src 'self'"); + + // The KVM currently needs to load images from base64 encoded strings. + // img-src 'self' data: is used to allow that. + // https://stackoverflow.com/questions/18447970/content-security-policy-data-not-working-for-base64-images-in-chrome-28 + res.addHeader("Content-Security-Policy", + "default-src 'self'; img-src 'self' data:"); res.addHeader("X-XSS-Protection", "1; " "mode=block"); res.addHeader("X-Content-Type-Options", "nosniff"); diff --git a/include/web_kvm.hpp b/include/web_kvm.hpp deleted file mode 100644 index 747a137b87..0000000000 --- a/include/web_kvm.hpp +++ /dev/null @@ -1,422 +0,0 @@ -#include <crow/app.h> - -#include <ast_jpeg_decoder.hpp> -#include <ast_video_puller.hpp> -#include <boost/endian/arithmetic.hpp> -#include <string> - -namespace crow -{ -namespace kvm -{ - -static const std::string rfb33VersionString = "RFB 003.003\n"; -static const std::string rfb37VersionString = "RFB 003.007\n"; -static const std::string rfb38VersionString = "RFB 003.008\n"; - -enum class RfbAuthScheme : uint8_t -{ - connection_failed = 0, - no_authentication = 1, - vnc_authentication = 2 -}; - -struct PixelFormatStruct -{ - boost::endian::big_uint8_t bitsPerPixel; - boost::endian::big_uint8_t depth; - boost::endian::big_uint8_t isBigEndian; - boost::endian::big_uint8_t isTrueColor; - boost::endian::big_uint16_t redMax; - boost::endian::big_uint16_t greenMax; - boost::endian::big_uint16_t blueMax; - boost::endian::big_uint8_t redShift; - boost::endian::big_uint8_t greenShift; - boost::endian::big_uint8_t blueShift; - boost::endian::big_uint8_t pad1; - boost::endian::big_uint8_t pad2; - boost::endian::big_uint8_t pad3; -}; - -struct ServerInitializationMsg -{ - boost::endian::big_uint16_t framebufferWidth; - boost::endian::big_uint16_t framebufferHeight; - PixelFormatStruct pixelFormat; - boost::endian::big_uint32_t nameLength; -}; - -enum class client_to_server_msg_type : uint8_t -{ - set_pixel_format = 0, - fix_color_map_entries = 1, - set_encodings = 2, - framebuffer_update_request = 3, - key_event = 4, - pointer_event = 5, - client_cut_text = 6 -}; - -enum class server_to_client_message_type : uint8_t -{ - framebuffer_update = 0, - set_color_map_entries = 1, - bell_message = 2, - server_cut_text = 3 -}; - -struct SetPixelFormatMsg -{ - boost::endian::big_uint8_t pad1; - boost::endian::big_uint8_t pad2; - boost::endian::big_uint8_t pad3; - PixelFormatStruct pixelFormat; -}; - -struct FrameBufferUpdateReq -{ - boost::endian::big_uint8_t incremental; - boost::endian::big_uint16_t xPosition; - boost::endian::big_uint16_t yPosition; - boost::endian::big_uint16_t width; - boost::endian::big_uint16_t height; -}; - -struct KeyEventMsg -{ - boost::endian::big_uint8_t downFlag; - boost::endian::big_uint8_t pad1; - boost::endian::big_uint8_t pad2; - boost::endian::big_uint32_t key; -}; - -struct PointerEventMsg -{ - boost::endian::big_uint8_t buttonMask; - boost::endian::big_uint16_t xPosition; - boost::endian::big_uint16_t yPosition; -}; - -struct ClientCutTextMsg -{ - std::vector<uint8_t> data; -}; - -enum class encoding_type : uint32_t -{ - raw = 0x00, - copy_rectangle = 0x01, - rising_rectangle = 0x02, - corre = 0x04, - hextile = 0x05, - zlib = 0x06, - tight = 0x07, - zlibhex = 0x08, - ultra = 0x09, - zrle = 0x10, - zywrle = 0x011, - cache_enable = 0xFFFF0001, - xor_enable = 0xFFFF0006, - server_state_ultranvc = 0xFFFF8000, - enable_keepAlive = 0xFFFF8001, - enableftp_protocol_version = 0xFFFF8002, - tight_compress_level_0 = 0xFFFFFF00, - tight_compress_level_9 = 0xFFFFFF09, - x_cursor = 0xFFFFFF10, - rich_cursor = 0xFFFFFF11, - pointer_pos = 0xFFFFFF18, - last_rect = 0xFFFFFF20, - new_framebuffer_size = 0xFFFFFF21, - tight_quality_level_0 = 0xFFFFFFE0, - tight_quality_level_9 = 0xFFFFFFE9 -}; - -struct FramebufferRectangle -{ - boost::endian::big_uint16_t x{}; - boost::endian::big_uint16_t y{}; - boost::endian::big_uint16_t width{}; - boost::endian::big_uint16_t height{}; - boost::endian::big_uint32_t encoding{}; - std::vector<uint8_t> data; -}; - -struct FramebufferUpdateMsg -{ - boost::endian::big_uint8_t messageType{}; - std::vector<FramebufferRectangle> rectangles; -}; - -inline std::string serialize(const FramebufferUpdateMsg& msg) -{ - // calculate the size of the needed vector for serialization - size_t vectorSize = 4; - for (const auto& rect : msg.rectangles) - { - vectorSize += 12 + rect.data.size(); - } - - std::string serialized(vectorSize, 0); - - size_t i = 0; - serialized[i++] = static_cast<char>( - server_to_client_message_type::framebuffer_update); // Type - serialized[i++] = 0; // Pad byte - boost::endian::big_uint16_t numberOfRectangles = msg.rectangles.size(); - std::memcpy(&serialized[i], &numberOfRectangles, - sizeof(numberOfRectangles)); - i += sizeof(numberOfRectangles); - - for (const auto& rect : msg.rectangles) - { - // copy the first part of the struct - size_t bufferSize = - sizeof(FramebufferRectangle) - sizeof(std::vector<uint8_t>); - std::memcpy(&serialized[i], &rect, bufferSize); - i += bufferSize; - - std::memcpy(&serialized[i], rect.data.data(), rect.data.size()); - i += rect.data.size(); - } - - return serialized; -} - -enum class VncState -{ - UNSTARTED, - AWAITING_CLIENT_VERSION, - AWAITING_CLIENT_AUTH_METHOD, - AWAITING_CLIENT_INIT_msg, - MAIN_LOOP -}; - -class ConnectionMetadata -{ - public: - ConnectionMetadata(){}; - - VncState vncState{VncState::UNSTARTED}; -}; - -using meta_list = std::vector<ConnectionMetadata>; -meta_list connectionStates(10); - -ConnectionMetadata meta; - -template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app) -{ - BMCWEB_ROUTE(app, "/kvmws") - .websocket() - .onopen([&](crow::websocket::Connection& conn) { - if (meta.vncState == VncState::UNSTARTED) - { - meta.vncState = VncState::AWAITING_CLIENT_VERSION; - conn.sendBinary(rfb38VersionString); - } - else - { // SHould never happen - conn.close(); - } - }) - .onclose( - [&](crow::websocket::Connection& conn, const std::string& reason) { - meta.vncState = VncState::UNSTARTED; - }) - .onmessage([&](crow::websocket::Connection& conn, - const std::string& data, bool is_binary) { - switch (meta.vncState) - { - case VncState::AWAITING_CLIENT_VERSION: - { - std::cout << "Client sent: " << data; - if (data == rfb38VersionString || - data == rfb37VersionString) - { - std::string authTypes{ - 1, (uint8_t)RfbAuthScheme::no_authentication}; - conn.sendBinary(authTypes); - meta.vncState = VncState::AWAITING_CLIENT_AUTH_METHOD; - } - else if (data == rfb33VersionString) - { - // TODO(ed) Support older protocols - meta.vncState = VncState::UNSTARTED; - conn.close(); - } - else - { - // TODO(ed) Support older protocols - meta.vncState = VncState::UNSTARTED; - conn.close(); - } - } - break; - case VncState::AWAITING_CLIENT_AUTH_METHOD: - { - std::string securityResult{{0, 0, 0, 0}}; - if (data[0] == (uint8_t)RfbAuthScheme::no_authentication) - { - meta.vncState = VncState::AWAITING_CLIENT_INIT_msg; - } - else - { - // Mark auth as failed - securityResult[3] = 1; - meta.vncState = VncState::UNSTARTED; - } - conn.sendBinary(securityResult); - } - break; - case VncState::AWAITING_CLIENT_INIT_msg: - { - // Now send the server initialization - ServerInitializationMsg serverInitMsg{}; - serverInitMsg.framebufferWidth = 800; - serverInitMsg.framebufferHeight = 600; - serverInitMsg.pixelFormat.bitsPerPixel = 32; - serverInitMsg.pixelFormat.isBigEndian = 0; - serverInitMsg.pixelFormat.isTrueColor = 1; - serverInitMsg.pixelFormat.redMax = 255; - serverInitMsg.pixelFormat.greenMax = 255; - serverInitMsg.pixelFormat.blueMax = 255; - serverInitMsg.pixelFormat.redShift = 16; - serverInitMsg.pixelFormat.greenShift = 8; - serverInitMsg.pixelFormat.blueShift = 0; - serverInitMsg.nameLength = 0; - std::cout << "size: " << sizeof(serverInitMsg); - // TODO(ed) this is ugly. Crow should really have a span - // type interface to avoid the copy, but alas, today it does - // not. - std::string s(reinterpret_cast<char*>(&serverInitMsg), - sizeof(serverInitMsg)); - std::cout << "s.size() " << s.size(); - conn.sendBinary(s); - meta.vncState = VncState::MAIN_LOOP; - } - break; - case VncState::MAIN_LOOP: - { - if (data.size() >= sizeof(client_to_server_msg_type)) - { - auto type = - static_cast<client_to_server_msg_type>(data[0]); - std::cout << "Received client message type " - << static_cast<std::size_t>(type) << "\n"; - switch (type) - { - case client_to_server_msg_type::set_pixel_format: - { - } - break; - - case client_to_server_msg_type:: - fix_color_map_entries: - { - } - break; - case client_to_server_msg_type::set_encodings: - { - } - break; - case client_to_server_msg_type:: - framebuffer_update_request: - { - // Make sure the buffer is long enough to handle - // what we're about to do - if (data.size() >= - sizeof(FrameBufferUpdateReq) + - sizeof(client_to_server_msg_type)) - { - auto msg = reinterpret_cast< - const FrameBufferUpdateReq*>( - data.data() + // NOLINT - sizeof(client_to_server_msg_type)); - // TODO(ed) find a better way to do this - // deserialization - - // Todo(ed) lifecycle of the video puller - // and decoder should be with the websocket, - // not recreated every time - ast_video::SimpleVideoPuller p; - p.initialize(); - auto out = p.readVideo(); - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, - out.mode, out.ySelector, - out.uvSelector); - - FramebufferUpdateMsg bufferUpdateMsg; - - // If the viewer is requesting a full - // update, force write of all pixels - - FramebufferRectangle thisRect; - thisRect.x = msg->xPosition; - thisRect.y = msg->yPosition; - thisRect.width = out.width; - thisRect.height = out.height; - thisRect.encoding = static_cast<uint8_t>( - encoding_type::raw); - std::cout << "Encoding is " - << thisRect.encoding; - thisRect.data.reserve( - static_cast<std::size_t>( - thisRect.width) * - static_cast<std::size_t>( - thisRect.height) * - 4); - std::cout << "Width " << out.width - << " Height " << out.height; - - for (int i = 0; i < out.width * out.height; - i++) - { - auto& pixel = d.outBuffer[i]; - thisRect.data.push_back(pixel.b); - thisRect.data.push_back(pixel.g); - thisRect.data.push_back(pixel.r); - thisRect.data.push_back(0); - } - - bufferUpdateMsg.rectangles.push_back( - std::move(thisRect)); - auto serialized = - serialize(bufferUpdateMsg); - - conn.sendBinary(serialized); - - } // TODO(Ed) handle error - } - - break; - - case client_to_server_msg_type::key_event: - { - } - break; - - case client_to_server_msg_type::pointer_event: - { - } - break; - - case client_to_server_msg_type::client_cut_text: - { - } - break; - - default: - break; - } - } - } - break; - case VncState::UNSTARTED: - // Error? TODO - break; - } - }); -} -} // namespace kvm -} // namespace crow
\ No newline at end of file diff --git a/src/getvideo_main.cpp b/src/getvideo_main.cpp deleted file mode 100644 index 849c75d539..0000000000 --- a/src/getvideo_main.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include <fcntl.h> -#include <unistd.h> - -#include <chrono> -#include <cstdio> -#include <cstdlib> -#include <fstream> -#include <iomanip> -#include <iostream> -#include <thread> -#include <vector> - -//#define BUILD_CIMG -#ifdef BUILD_CIMG -#define cimg_display 0 -#include <CImg.h> -#endif - -#include <ast_jpeg_decoder.hpp> -#include <ast_video_puller.hpp> - -int main() -{ - ast_video::RawVideoBuffer out; - bool have_hardware = false; - if (access("/dev/video", F_OK) != -1) - { - ast_video::SimpleVideoPuller p; - p.initialize(); - out = p.readVideo(); - } - else - { - FILE *fp = fopen("/home/ed/screendata.bin", "rb"); - if (fp != nullptr) - { - size_t newLen = fread(out.buffer.data(), sizeof(char), - out.buffer.size() * sizeof(long), fp); - if (ferror(fp) != 0) - { - fputs("Error reading file", stderr); - } - fclose(fp); - out.buffer.resize(newLen); - out.mode = ast_video::YuvMode::YUV444; - out.width = 800; - out.height = 600; - out.ySelector = 0; - out.uvSelector = 0; - } - } - - FILE *fp = fopen("/tmp/screendata.bin", "wb"); - fwrite(out.buffer.data(), sizeof(char), out.buffer.size(), fp); - fclose(fp); - - ast_video::AstJpegDecoder d; - d.decode(out.buffer, out.width, out.height, out.mode, out.ySelector, - out.uvSelector); -#ifdef BUILD_CIMG - cimg_library::CImg<unsigned char> image(out.width, out.height, 1, - 3 /*numchannels*/); - for (int y = 0; y < out.height; y++) - { - for (int x = 0; x < out.width; x++) - { - auto pixel = d.outBuffer[x + (y * out.width)]; - image(x, y, 0) = pixel.r; - image(x, y, 1) = pixel.g; - image(x, y, 2) = pixel.b; - } - } - image.save("/tmp/file2.bmp"); -#endif - - std::cout << "Done!\n"; - - return 1; -} diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp index 7c64f4c748..b357b4e1de 100644 --- a/src/webserver_main.cpp +++ b/src/webserver_main.cpp @@ -5,6 +5,7 @@ #include <dbus_monitor.hpp> #include <dbus_singleton.hpp> #include <image_upload.hpp> +#include <kvm_websocket.hpp> #include <memory> #include <obmc_console.hpp> #include <openbmc_dbus_rest.hpp> @@ -18,7 +19,6 @@ #include <ssl_key_handler.hpp> #include <string> #include <token_authorization_middleware.hpp> -#include <web_kvm.hpp> #include <webassets.hpp> #include <webserver_common.hpp> @@ -77,7 +77,7 @@ int main(int argc, char** argv) #endif #ifdef BMCWEB_ENABLE_KVM - crow::kvm::requestRoutes(app); + crow::obmc_kvm::requestRoutes(app); #endif #ifdef BMCWEB_ENABLE_REDFISH |