diff --git a/README.md b/README.md index dff03fd..f2be9cb 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ There are a lot of boards available that are all called ESP32-CAM. However, there are differences in CPU (type/speed/cores), how the camera is connected, presence of PSRAM or not... To select the right board use the table below and use the configuration that is listed below for your board: -| Board | Image | CPU | SRAM | Flash | PSRAM | Camera | | Site | +| Board | Image | CPU | SRAM | Flash | PSRAM | Camera | Extras | Manufacturer site | |--- |--- |--- |--- |--- | --- |--- |--- |--- | | Espressif ESP32-Wrover CAM | ![img](assets/boards/esp32-wrover-cam.jpg) | ESP32 | 520KB | 4Mb | 4MB | OV2640 | | | | AI-Thinker ESP32-CAM | ![img](assets/boards/ai-thinker-esp32-cam-ipex.jpg) ![img](assets/boards/ai-thinker-esp32-cam.jpg) | ESP32-S | 520KB | 4Mb | 4MB | OV2640 | | [https://docs.ai-thinker.com/esp32-cam](https://docs.ai-thinker.com/esp32-cam) | diff --git a/boards/esp32cam_ai_thinker.json b/boards/esp32cam_ai_thinker.json index 5c5fa8c..ed12cb8 100644 --- a/boards/esp32cam_ai_thinker.json +++ b/boards/esp32cam_ai_thinker.json @@ -32,7 +32,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/esp32cam_espressif_esp32s2_cam_board.json b/boards/esp32cam_espressif_esp32s2_cam_board.json index 4fb920f..dd8b292 100644 --- a/boards/esp32cam_espressif_esp32s2_cam_board.json +++ b/boards/esp32cam_espressif_esp32s2_cam_board.json @@ -32,7 +32,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/esp32cam_espressif_esp32s2_cam_header.json b/boards/esp32cam_espressif_esp32s2_cam_header.json index 212d0a9..2c0b347 100644 --- a/boards/esp32cam_espressif_esp32s2_cam_header.json +++ b/boards/esp32cam_espressif_esp32s2_cam_header.json @@ -32,7 +32,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/esp32cam_espressif_esp32s3_cam_lcd.json b/boards/esp32cam_espressif_esp32s3_cam_lcd.json index b07fd23..61aadca 100644 --- a/boards/esp32cam_espressif_esp32s3_cam_lcd.json +++ b/boards/esp32cam_espressif_esp32s3_cam_lcd.json @@ -34,7 +34,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/esp32cam_espressif_esp32s3_eye.json b/boards/esp32cam_espressif_esp32s3_eye.json index a65ccbb..7a9d165 100644 --- a/boards/esp32cam_espressif_esp32s3_eye.json +++ b/boards/esp32cam_espressif_esp32s3_eye.json @@ -34,7 +34,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/esp32cam_espressif_esp_eye.json b/boards/esp32cam_espressif_esp_eye.json index 2b6a722..1c3b0e5 100644 --- a/boards/esp32cam_espressif_esp_eye.json +++ b/boards/esp32cam_espressif_esp_eye.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld", "partitions": "huge_app.csv" }, @@ -32,7 +32,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=1'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/esp32cam_freenove_wrover_kit.json b/boards/esp32cam_freenove_wrover_kit.json index 3c9b5dd..fde4dbd 100644 --- a/boards/esp32cam_freenove_wrover_kit.json +++ b/boards/esp32cam_freenove_wrover_kit.json @@ -32,7 +32,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/esp32cam_m5stack_camera.json b/boards/esp32cam_m5stack_camera.json index 7ca87cf..11c18fc 100644 --- a/boards/esp32cam_m5stack_camera.json +++ b/boards/esp32cam_m5stack_camera.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld", "partitions": "huge_app.csv" }, @@ -28,7 +28,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=1'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_DRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'", + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'", "'-D GROVE_SDA=13'", "'-D GROVE_SCL=4'" ], diff --git a/boards/esp32cam_m5stack_camera_psram.json b/boards/esp32cam_m5stack_camera_psram.json index d112035..0b1c0ac 100644 --- a/boards/esp32cam_m5stack_camera_psram.json +++ b/boards/esp32cam_m5stack_camera_psram.json @@ -30,7 +30,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'", + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'", "'-D GROVE_SDA=13'", "'-D GROVE_SCL=4'" ], diff --git a/boards/esp32cam_m5stack_esp32cam.json b/boards/esp32cam_m5stack_esp32cam.json index ee41ecf..1f6f23d 100644 --- a/boards/esp32cam_m5stack_esp32cam.json +++ b/boards/esp32cam_m5stack_esp32cam.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld", "partitions": "huge_app.csv" }, @@ -32,7 +32,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'", + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'", "'-D MICROPHONE_GPIO=32'", "'-D GROVE_SDA=13'", "'-D GROVE_SCL=4'" diff --git a/boards/esp32cam_m5stack_unitcam.json b/boards/esp32cam_m5stack_unitcam.json index 92672be..df7615b 100644 --- a/boards/esp32cam_m5stack_unitcam.json +++ b/boards/esp32cam_m5stack_unitcam.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld", "partitions": "huge_app.csv" }, @@ -30,7 +30,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=1'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_DRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/esp32cam_m5stack_unitcams3.json b/boards/esp32cam_m5stack_unitcams3.json index 897b52d..7d1c8a9 100644 --- a/boards/esp32cam_m5stack_unitcams3.json +++ b/boards/esp32cam_m5stack_unitcams3.json @@ -36,7 +36,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_DRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'", + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'", "'-D I2C_MEMS_SDA=17'", "'-D I2C_MEMS_SCL=41'", "'-D TF_CS=9'", diff --git a/boards/esp32cam_m5stack_wide.json b/boards/esp32cam_m5stack_wide.json index d502897..ef4c688 100644 --- a/boards/esp32cam_m5stack_wide.json +++ b/boards/esp32cam_m5stack_wide.json @@ -1,6 +1,6 @@ { "build": { - "arduino":{ + "arduino": { "ldscript": "esp32_out.ld", "partitions": "huge_app.csv" }, @@ -30,7 +30,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/boards/esp32cam_seeed_xiao_esp32s3_sense.json b/boards/esp32cam_seeed_xiao_esp32s3_sense.json index ee742bc..30ef0bf 100644 --- a/boards/esp32cam_seeed_xiao_esp32s3_sense.json +++ b/boards/esp32cam_seeed_xiao_esp32s3_sense.json @@ -36,7 +36,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=2'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_PSRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'", + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'", "'-D I2C_MEMS_SDA=41'", "'-D I2C_MEMS_SCL=42'", "'-D TF_CS=21'", diff --git a/boards/esp32cam_ttgo_t_camera.json b/boards/esp32cam_ttgo_t_camera.json index 3cd7062..f903d0d 100644 --- a/boards/esp32cam_ttgo_t_camera.json +++ b/boards/esp32cam_ttgo_t_camera.json @@ -28,7 +28,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=1'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_DRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'", + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'", "'-D LCD_SSD1306_PIN_SDA=21'", "'-D LCD_SSD1306_PIN_SCL=22'", "'-D BUTTON_RIGHT_PIN=34'", diff --git a/boards/esp32cam_ttgo_t_journal.json b/boards/esp32cam_ttgo_t_journal.json index 928ae27..5ec8fd7 100644 --- a/boards/esp32cam_ttgo_t_journal.json +++ b/boards/esp32cam_ttgo_t_journal.json @@ -28,7 +28,7 @@ "'-D CAMERA_CONFIG_LEDC_CHANNEL=LEDC_CHANNEL_0'", "'-D CAMERA_CONFIG_FB_COUNT=1'", "'-D CAMERA_CONFIG_FB_LOCATION=CAMERA_FB_IN_DRAM'", - "'-D SCCB_I2C_PORT=I2C_NUM_0'" + "'-D CAMERA_CONFIG_SCCB_I2C_PORT=I2C_NUM_0'" ], "f_cpu": "240000000L", "f_flash": "40000000L", diff --git a/dotnet_riscv b/dotnet_riscv new file mode 160000 index 0000000..70e3cb6 --- /dev/null +++ b/dotnet_riscv @@ -0,0 +1 @@ +Subproject commit 70e3cb657b88224d7d98e0aa8d0d8f7f9ed5c288 diff --git a/include/settings.h b/include/settings.h index 9422efa..cf997cb 100644 --- a/include/settings.h +++ b/include/settings.h @@ -9,6 +9,12 @@ #define OTA_PASSWORD "ESP32CAM-RTSP" +// Time servers +#define NTP_SERVER_1 "nl.pool.ntp.org" +#define NTP_SERVER_2 "europe.pool.ntp.org" +#define NTP_SERVER_3 "time.nist.gov" +#define NTP_SERVERS NTP_SERVER_1, NTP_SERVER_2, NTP_SERVER_3 + #define RTSP_PORT 554 #define DEFAULT_FRAME_DURATION 200 diff --git a/lib/micro-jpg/include/jpg.h b/lib/micro-jpg/include/jpg.h new file mode 100644 index 0000000..1862bd4 --- /dev/null +++ b/lib/micro-jpg/include/jpg.h @@ -0,0 +1,18 @@ +#include + +#include "jpg_section.h" + +class jpg +{ +public: + bool decode(const uint8_t *jpg, size_t size); + + const jpg_section_dqt_t *quantization_table_luminance_; + const jpg_section_dqt_t *quantization_table_chrominance_; + + const uint8_t *jpeg_data_start; + const uint8_t *jpeg_data_end; + +private: + static const jpg_section_t *find_jpg_section(const uint8_t **ptr, const uint8_t *end, jpg_section_t::jpg_section_flag flag); +}; \ No newline at end of file diff --git a/lib/micro-jpg/include/jpg_section.h b/lib/micro-jpg/include/jpg_section.h new file mode 100644 index 0000000..506cbfa --- /dev/null +++ b/lib/micro-jpg/include/jpg_section.h @@ -0,0 +1,107 @@ +#pragma once + +#include +#include + +// http://www.ietf.org/rfc/rfc2345.txt Each table is an array of 64 values given in zig-zag order, identical to the format used in a JFIF DQT marker segment. +constexpr size_t jpeg_quantization_table_length = 64; + +typedef struct __attribute__((packed)) +{ + enum jpg_section_flag : uint8_t + { + DATA = 0x00, + SOF0 = 0xc0, + SOF1 = 0xc1, + SOF2 = 0xc2, + SOF3 = 0xc3, + DHT = 0xc4, + SOF5 = 0xc5, + SOF6 = 0xc6, + SOF7 = 0xc7, + JPG = 0xc8, + SOF9 = 0xc9, + SOF10 = 0xca, + SOF11 = 0xcb, + DAC = 0xcc, + SOF13 = 0xcd, + SOF14 = 0xce, + SOF15 = 0xcf, + RST0 = 0xd0, + RST1 = 0xd1, + RST2 = 0xd2, + RST3 = 0xd3, + RST4 = 0xd4, + RST5 = 0xd5, + RST6 = 0xd6, + RST7 = 0xd7, + SOI = 0xd8, + EOI = 0xd9, + SOS = 0xda, + DQT = 0xdb, + DNL = 0xdc, + DRI = 0xdd, + DHP = 0xde, + EXP = 0xdf, + APP0 = 0xe0, + APP1 = 0xe1, + APP2 = 0xe2, + APP3 = 0xe3, + APP4 = 0xe4, + APP5 = 0xe5, + APP6 = 0xe6, + APP7 = 0xe7, + APP8 = 0xe8, + APP9 = 0xe9, + APP10 = 0xea, + APP11 = 0xeb, + APP12 = 0xec, + APP13 = 0xed, + APP14 = 0xee, + APP15 = 0xef, + JPG0 = 0xf0, + JPG1 = 0xf1, + JPG2 = 0xf2, + JPG3 = 0xf3, + JPG4 = 0xf4, + JPG5 = 0xf5, + JPG6 = 0xf6, + JPG7 = 0xf7, + JPG8 = 0xf8, + JPG9 = 0xf9, + COM = 0xfe, + JPG10 = 0xfa, + JPG11 = 0xfb, + JPG12 = 0xfc, + JPG13 = 0xfd + }; + + const uint8_t framing; // 0xff + const jpg_section_flag flag; + const uint8_t length_msb; + const uint8_t length_lsb; + const uint8_t data[]; + + static bool is_valid_flag(const jpg_section_flag flag); + static const char *flag_name(const jpg_section_flag flag); + uint16_t data_length() const; + uint16_t section_length() const; +} jpg_section_t; + +typedef struct __attribute__((packed)) // 0xffe0 +{ + char identifier[5] = {'J', 'F', 'I', 'F', 0}; // JFIF identifier, zero-terminated + uint8_t version_major = 1; + uint8_t version_minor = 1; // JFIF version 1.1 + uint8_t density_units = 0; // no density units specified + uint16_t density_hor = 1; + uint16_t density_ver = 1; // density: 1 pixel "per pixel" horizontally and vertically + uint8_t thumbnail_hor = 0; + uint8_t thumbnail_ver = 0; // no thumbnail (size 0 x 0) +} jpg_section_app0_t; + +typedef struct __attribute__((packed)) // 0xffdb +{ + uint8_t id; // 0= quantLuminance, 1= quantChrominance + uint8_t data[jpeg_quantization_table_length]; +} jpg_section_dqt_t; \ No newline at end of file diff --git a/lib/micro-jpg/library.json b/lib/micro-jpg/library.json new file mode 100644 index 0000000..83bfb51 --- /dev/null +++ b/lib/micro-jpg/library.json @@ -0,0 +1,14 @@ +{ + "name": "micro-jpg", + "version": "1.0.0", + "description": "JPEG library", + "keywords": "", + "repository": { + "type": "git", + "url": "https://github.com/rzeldent/" + }, + "build": { + "srcDir": "src/", + "includeDir": "include/" + } +} \ No newline at end of file diff --git a/lib/micro-jpg/src/jpg.cpp b/lib/micro-jpg/src/jpg.cpp new file mode 100644 index 0000000..502c1f5 --- /dev/null +++ b/lib/micro-jpg/src/jpg.cpp @@ -0,0 +1,111 @@ +#include +#include "jpg.h" + +const jpg_section_t *jpg::find_jpg_section(const uint8_t **ptr, const uint8_t *end, jpg_section_t::jpg_section_flag flag) +{ + log_d("find_jpeg_section 0x%02x (%s)", flag, jpg_section_t::flag_name(flag)); + while (*ptr < end) + { + // flag, len MSB, len LSB + auto section = reinterpret_cast((*ptr)); + if (section->framing != 0xff) + { + log_e("Expected framing 0xff but found: 0x%02x", section->framing); + break; + } + + if (!jpg_section_t::is_valid_flag(section->flag)) + { + log_d("Unknown section 0x%02x", flag); + return nullptr; + } + + // Advance pointer section has a length, so not SOI (0xd8) and EOI (0xd9) + *ptr += section->section_length(); + if (section->flag == flag) + { + log_d("Found section 0x%02x (%s), %d bytes", flag, jpg_section_t::flag_name(section->flag), section->section_length()); + return section; + } + + log_d("Skipping section: 0x%02x (%s), %d bytes", section->flag, jpg_section_t::flag_name(section->flag), section->section_length()); + } + + // Not found + return nullptr; +} + +// See https://create.stephan-brumme.com/toojpeg/ +bool jpg::decode(const uint8_t *data, size_t size) +{ + log_d("decode_jpeg"); + // Look for start jpeg file (0xd8) + auto ptr = data; + auto end = ptr + size; + + // Check for SOI (start of image) 0xff, 0xd8 + if (!find_jpg_section(&ptr, end, jpg_section_t::jpg_section_flag::SOI)) + { + log_e("No valid start of image marker found"); + return false; + } + + // First quantization table (Luminance - black & white images) + const jpg_section_t *quantization_table_section; + if (!(quantization_table_section = find_jpg_section(&ptr, end, jpg_section_t::jpg_section_flag::DQT))) + { + log_e("No quantization_table_luminance section found"); + return false; + } + + if (quantization_table_section->data_length() != sizeof(jpg_section_dqt_t)) + { + log_w("Invalid length of quantization_table_luminance section. Expected %d but read %d", sizeof(jpg_section_dqt_t), quantization_table_section->data_length()); + return false; + } + + quantization_table_luminance_ = reinterpret_cast(quantization_table_section->data); + + // Second quantization table (Chrominance - color images) + if (!(quantization_table_section = find_jpg_section(&ptr, end, jpg_section_t::jpg_section_flag::DQT))) + { + log_w("No quantization_table_chrominance section found"); + return false; + } + + if (quantization_table_section->data_length() != sizeof(jpg_section_dqt_t)) + { + log_w("Invalid length of quantization_table_chrominance section. Expected %d but read %d", sizeof(jpg_section_dqt_t), quantization_table_section->data_length()); + return false; + } + + quantization_table_chrominance_ = reinterpret_cast(quantization_table_section->data); + + // Start of scan + if (!find_jpg_section(&ptr, end, jpg_section_t::jpg_section_flag::SOS)) + { + log_e("No start of scan section found"); + return false; + } + + // Start of the data sections + jpeg_data_start = ptr; + + log_d("Skipping over data sections"); + // Scan over all the sections. 0xff followed by not zero, is a new section + while (ptr < end - 1 && (ptr[0] != 0xff || ptr[1] == 0)) + ptr++; + + // Check if marker is an end of image marker + if (!find_jpg_section(&ptr, end, jpg_section_t::jpg_section_flag::EOI)) + { + log_e("No end of image marker found"); + return false; + } + + jpeg_data_end = ptr; + + log_d("Total jpeg data: %d bytes", jpeg_data_end - jpeg_data_start); + + return true; +} diff --git a/lib/micro-jpg/src/jpg_section.cpp b/lib/micro-jpg/src/jpg_section.cpp new file mode 100644 index 0000000..ba908bf --- /dev/null +++ b/lib/micro-jpg/src/jpg_section.cpp @@ -0,0 +1,154 @@ +#include "jpg_section.h" + +uint16_t jpg_section_t::data_length() const +{ + return (length_msb << 8) + length_lsb - sizeof(jpg_section_t::length_msb)- sizeof(jpg_section_t::length_lsb); +} + +uint16_t jpg_section_t::section_length() const +{ + return flag == SOI || flag == EOI ? sizeof(jpg_section_t::framing) + sizeof(jpg_section_t::flag) : sizeof(jpg_section_t::framing) + sizeof(jpg_section_t::flag) + (length_msb << 8) + length_lsb; +} + +bool jpg_section_t::is_valid_flag(const jpg_section_flag flag) +{ + return flag >= SOF0 && flag <= COM; +} + +// from: https://www.disktuna.com/list-of-jpeg-markers/ +const char *jpg_section_t::flag_name(const jpg_section_flag flag) +{ + switch (flag) + { + case DATA: + return "DATA"; // DATA + case SOF0: + return "SOF0"; // Start of Frame 0 Baseline DCT + case SOF1: + return "SOF1"; // Start of Frame 1 Extended Sequential DCT + case SOF2: + return "SOF2"; // Start of Frame 2 Progressive DCT + case SOF3: + return "SOF3"; // Start of Frame 3 Lossless (sequential) + case DHT: + return "DHT"; // Define Huffman Table + case SOF5: + return "SOF5"; // Start of Frame 5 Differential sequential DCT + case SOF6: + return "SOF6"; // Start of Frame 6 Differential progressive DCT + case SOF7: + return "SOF7"; // Start of Frame 7 Differential lossless (sequential) + case JPG: + return "JPG"; // JPEG Extensions + case SOF9: + return "SOF9"; // Start of Frame 9 Extended sequential DCT, Arithmetic coding + case SOF10: + return "SOF10"; // Start of Frame 10 Progressive DCT, Arithmetic coding + case SOF11: + return "SOF11"; // Start of Frame 11 Lossless (sequential), Arithmetic coding + case DAC: + return "DAC"; // Define Arithmetic Coding + case SOF13: + return "SOF13"; // Start of Frame 13 Differential sequential DCT, Arithmetic coding + case SOF14: + return "SOF14"; // Start of Frame 14 Differential progressive DCT, Arithmetic coding + case SOF15: + return "SOF15"; // Start of Frame 15 Differential lossless (sequential), Arithmetic coding + case RST0: + return "RST0"; // Restart Marker 0 + case RST1: + return "RST1"; // Restart Marker 1 + case RST2: + return "RST2"; // Restart Marker 2 + case RST3: + return "RST3"; // Restart Marker 3 + case RST4: + return "RST4"; // Restart Marker 4 + case RST5: + return "RST5"; // Restart Marker 5 + case RST6: + return "RST6"; // Restart Marker 6 + case RST7: + return "RST7"; // Restart Marker 7 + case SOI: + return "SOI"; // Start of Image + case EOI: + return "EOI"; // End of Image + case SOS: + return "SOS"; // Start of Scan + case DQT: + return "DQT"; // Define Quantization Table + case DNL: + return "DNL"; // Define Number of Lines (Not common) + case DRI: + return "DRI"; // Define Restart Interval + case DHP: + return "DHP"; // Define Hierarchical Progression (Not common) + case EXP: + return "EXP"; // Expand Reference Component (Not common) + case APP0: + return "APP0"; // Application Segment 0 JFIF – JFIF JPEG image, AVI1 – Motion JPEG (MJPG) + case APP1: + return "APP1"; // Application Segment 1 EXIF Metadata, TIFF IFD format, JPEG Thumbnail (160×120) Adobe XMP + case APP2: + return "APP2"; // Application Segment 2 ICC color profile, FlashPix + case APP3: + return "APP3"; // Application Segment 3 (Not common) JPS Tag for Stereoscopic JPEG images + case APP4: + return "APP4"; // Application Segment 4 (Not common) + case APP5: + return "APP5"; // Application Segment 5 (Not common) + case APP6: + return "APP6"; // Application Segment 6 (Not common) NITF Lossles profile + case APP7: + return "APP7"; // Application Segment 7 (Not common) + case APP8: + return "APP8"; // Application Segment 8 (Not common) + case APP9: + return "APP9"; // Application Segment 9 (Not common) + case APP10: + return "APP10"; // Application Segment 10 PhoTags (Not common) ActiveObject (multimedia messages / captions) + case APP11: + return "APP11"; // Application Segment 11 (Not common) HELIOS JPEG Resources (OPI Postscript) + case APP12: + return "APP12"; // Application Segment 12 Picture Info (older digicams), Photoshop Save for Web: Ducky + case APP13: + return "APP13"; // Application Segment 13 Photoshop Save As: IRB, 8BIM, IPTC + case APP14: + return "APP14"; // Application Segment 14 (Not common) + case APP15: + return "APP15"; // Application Segment 15 (Not common) + case JPG0: + return "JPG0"; // JPEG Extension 0 + case JPG1: + return "JPG1"; // JPEG Extension 1 + case JPG2: + return "JPG2"; // JPEG Extension 2 + case JPG3: + return "JPG3"; // JPEG Extension 3 + case JPG4: + return "JPG4"; // JPEG Extension 4 + case JPG5: + return "JPG5"; // JPEG Extension 5 + case JPG6: + return "JPG6"; // JPEG Extension 6 + case JPG7: + return "JPG7"; // SOF48 JPEG Extension 7 JPEG-LS Lossless JPEG + case JPG8: + return "JPG8"; // LSE JPEG Extension 8 JPEG-LS Extension Lossless JPEG Extension Parameters + case JPG9: + return "JPG9"; // JPEG Extension 9 (Not common) + case JPG10: + return "JPG10"; // JPEG Extension 10 (Not common) + case JPG11: + return "JPG11"; // JPEG Extension 11 (Not common) + case JPG12: + return "JPG12"; // JPEG Extension 12 (Not common) + case JPG13: + return "JPG13"; // JPEG Extension 13 (Not common) + case COM: + return "COM"; // Comment + } + + return "Unknown"; +} diff --git a/lib/micro-rtsp-server/include/micro_rtsp_camera.h b/lib/micro-rtsp-server/include/micro_rtsp_camera.h new file mode 100644 index 0000000..534eab2 --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_camera.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +class micro_rtsp_camera : public micro_rtsp_source +{ +public: + micro_rtsp_camera(); + virtual ~micro_rtsp_camera(); + + esp_err_t initialize(camera_config_t *camera_config); + esp_err_t deinitialize(); + + virtual void update_frame(); + + virtual uint8_t *data() const { return fb_->buf; } + virtual size_t width() const { return fb_->width; } + virtual size_t height() const { return fb_->height; } + virtual size_t size() const { return fb_->len; } + +private: + esp_err_t init_result_; + camera_fb_t *fb_; +}; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtsp_requests.h b/lib/micro-rtsp-server/include/micro_rtsp_requests.h new file mode 100644 index 0000000..cf6a2c3 --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_requests.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +class micro_rtsp_requests +{ +public: + std::string process_request(const std::string& request); + bool active() const { return stream_active_; } + +private: + // enum rtsp_command + // { + // rtsp_command_unknown, + // rtsp_command_options, // OPTIONS + // rtsp_command_describe, // DESCRIBE + // rtsp_command_setup, // SETUP + // rtsp_command_play, // PLAY + // rtsp_command_teardown // TEARDOWN + // }; + + static const std::string available_stream_name_; + + //rtsp_command parse_command(const std::string &request); + //static bool parse_cseq(const std::string &line, unsigned long &cseq); + bool parse_client_port(const std::string &request); + //bool parse_stream_url(const std::string &request); + + //static std::string date_header(); + static std::string handle_rtsp_error(unsigned long cseq, unsigned short code, const std::string &message); + + static std::string handle_options(unsigned long cseq); + static std::string handle_describe(unsigned long cseq, const std::string &request); + std::string handle_setup(unsigned long cseq, const std::map &request); + std::string handle_play(unsigned long cseq); + std::string handle_teardown(unsigned long cseq); + + //unsigned long cseq_; + + // std::string host_url_; + // unsigned short host_port_; + // std::string stream_name_; + + bool tcp_transport_; + unsigned short start_client_port_; + unsigned short end_client_port_; + + unsigned short rtp_streamer_port_; + unsigned short rtcp_streamer_port_; + + unsigned long rtsp_session_id_; + + bool stream_active_; + bool stream_stopped_; +}; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtsp_server.h b/lib/micro-rtsp-server/include/micro_rtsp_server.h new file mode 100644 index 0000000..09bdff4 --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_server.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#include +#include + +#include "micro_rtsp_camera.h" +#include "micro_rtsp_requests.h" +#include "micro_rtsp_streamer.h" + +class micro_rtsp_server : WiFiServer +{ +public: + micro_rtsp_server(micro_rtsp_source &source); + ~micro_rtsp_server(); + + void begin(unsigned short port = 554); + void end(); + + unsigned get_frame_interval() const { return frame_interval_; } + unsigned set_frame_interval(unsigned value) { return frame_interval_ = value; } + + void loop(); + + size_t clients() const { return clients_.size(); } + + class rtsp_client : public WiFiClient, public micro_rtsp_requests + { + public: + rtsp_client(const WiFiClient &client); + ~rtsp_client(); + + void handle_request(); + }; + +private: + micro_rtsp_source &source_; + unsigned frame_interval_; + unsigned long next_frame_update_; + unsigned long next_check_client_; + micro_rtsp_streamer streamer_; + std::list clients_; +}; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtsp_source.h b/lib/micro-rtsp-server/include/micro_rtsp_source.h new file mode 100644 index 0000000..1079a25 --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_source.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include + +// Interface for a video source +class micro_rtsp_source +{ +public: + virtual void update_frame() = 0; + + virtual uint8_t *data() const = 0; + virtual size_t width() const = 0; + virtual size_t height() const = 0; + virtual size_t size() const = 0; +}; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtsp_streamer.h b/lib/micro-rtsp-server/include/micro_rtsp_streamer.h new file mode 100644 index 0000000..edbbd96 --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_streamer.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include // Add this line to include the definition of micro_rtsp_camera +#include + +// https://en.wikipedia.org/wiki/Maximum_transmission_unit +constexpr size_t max_wifi_mtu = 2304; +// Payload JPG - https://www.ietf.org/rfc/rfc1890.txt +constexpr uint8_t RTP_PAYLOAD_JPG = 26; + +// One of the types below will be returned, the jpeg_packet_with_quantization_t for the first packet, then the jpeg_packet_t + +typedef struct __attribute__((packed)) +{ + rtp_over_tcp_hdr_t rtp_over_tcp_hdr; + rtp_hdr_t rtp_hdr; + jpeg_hdr_t jpeg_hdr; + jpeg_hdr_qtable_t jpeg_hdr_qtable; + uint8_t quantization_table_luminance[jpeg_quantization_table_length]; + uint8_t quantization_table_chrominance[jpeg_quantization_table_length]; + uint8_t jpeg_data[]; +} jpeg_packet_with_quantization_t; + +typedef struct __attribute__((packed)) +{ + rtp_over_tcp_hdr_t rtp_over_tcp_hdr; + rtp_hdr_t rtp_hdr; + jpeg_hdr_t jpeg_hdr; + uint8_t jpeg_data[]; +} jpeg_packet_t; + +class micro_rtsp_streamer +{ +public: + micro_rtsp_streamer(const micro_rtsp_source& source); + rtp_over_tcp_hdr_t *create_jpg_packet(const uint8_t *jpg_scan, const uint8_t *jpg_scan_end, uint8_t **jpg_offset, const uint32_t timestamp, const uint8_t *quantization_table_luminance, const uint8_t *quantization_table_chrominance); + +private: + const micro_rtsp_source& source_; + uint32_t ssrc_; + uint16_t sequence_number_; +}; \ No newline at end of file diff --git a/lib/micro-rtsp-server/include/micro_rtsp_structs.h b/lib/micro-rtsp-server/include/micro_rtsp_structs.h new file mode 100644 index 0000000..671efac --- /dev/null +++ b/lib/micro-rtsp-server/include/micro_rtsp_structs.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +// https://www.ietf.org/rfc/rfc2326#section-10.12 +typedef struct __attribute__((packed)) +{ + char magic = '$'; // Magic encapsulation ASCII dollar sign (24 hexadecimal) + uint8_t channel; // Channel identifier + uint16_t length; // Network order +} rtp_over_tcp_hdr_t; + +// RTP data header - http://www.ietf.org/rfc/rfc3550.txt +typedef struct __attribute__((packed)) +{ + uint16_t version : 2; // protocol version + uint16_t padding : 1; // padding flag + uint16_t extension : 1; // header extension flag + uint16_t cc : 4; // CSRC count + uint16_t marker : 1; // marker bit + uint16_t pt : 7; // payload type + uint16_t seq : 16; // sequence number + uint32_t ts; // timestamp + uint32_t ssrc; // synchronization source +} rtp_hdr_t; + +// https://datatracker.ietf.org/doc/html/rfc2435 +typedef struct __attribute__((packed)) +{ + uint32_t tspec : 8; // type-specific field + uint32_t off : 24; // fragment byte offset + uint8_t type; // id of jpeg decoder params + uint8_t q; // Q values 0-127 indicate the quantization tables. JPEG types 0 and 1 (and their corresponding types 64 and 65) + uint8_t width; // frame width in 8 pixel blocks + uint8_t height; // frame height in 8 pixel blocks +} jpeg_hdr_t; + +typedef struct __attribute__((packed)) +{ + uint16_t dri; + uint16_t f : 1; + uint16_t l : 1; + uint16_t count : 14; +} jpeg_hdr_rst_t; + +typedef struct __attribute__((packed)) +{ + uint8_t mbz; + uint8_t precision; + uint16_t length; +} jpeg_hdr_qtable_t; diff --git a/lib/micro-rtsp-server/library.json b/lib/micro-rtsp-server/library.json new file mode 100644 index 0000000..9bb0a5f --- /dev/null +++ b/lib/micro-rtsp-server/library.json @@ -0,0 +1,20 @@ +{ + "name": "micro-rtsp-streamer", + "version": "1.0.0", + "description": "RTSP Server", + "keywords": "", + "repository": { + "type": "git", + "url": "https://github.com/rzeldent/micro-rtsp-streamer" + }, + + "build": { + "srcDir": "src/", + "includeDir": "include/" + }, + + "dependencies": { + "micro-jpg": "^1.0.0", + "espressif/esp32-camera": "^2.0.4" + } +} \ No newline at end of file diff --git a/lib/micro-rtsp-server/src/micro_rtsp_camera.cpp b/lib/micro-rtsp-server/src/micro_rtsp_camera.cpp new file mode 100644 index 0000000..0ea4462 --- /dev/null +++ b/lib/micro-rtsp-server/src/micro_rtsp_camera.cpp @@ -0,0 +1,39 @@ +#include + +#include "micro_rtsp_camera.h" + +micro_rtsp_camera::micro_rtsp_camera() +{ + init_result_ == ESP_FAIL; +} + +micro_rtsp_camera::~micro_rtsp_camera() +{ + deinitialize(); +} + +esp_err_t micro_rtsp_camera::initialize(camera_config_t *camera_config) +{ + log_v("camera_config={.pin_pwdn:%u,.pin_reset:%u,.pin_xclk:%u,.pin_sccb_sda:%u,.pin_sccb_scl:%u,.pin_d7:%u,.pin_d6:%u,.pin_d5:%u,.pin_d4:%u,.pin_d3:%u,.pin_d2:%u,.pin_d1:%u,.pin_d0:%u,.pin_vsync:%u,.pin_href:%u,.pin_pclk:%u,.xclk_freq_hz:%d,.ledc_timer:%u,ledc_channel:%u,.pixel_format:%d,.frame_size:%d,.jpeg_quality:%d,.fb_count:%d,.fb_location%d,.grab_mode:%d,sccb_i2c_port:%d}", camera_config->pin_pwdn, camera_config->pin_reset, camera_config->pin_xclk, camera_config->pin_sccb_sda, camera_config->pin_sccb_scl, camera_config->pin_d7, camera_config->pin_d6, camera_config->pin_d5, camera_config->pin_d4, camera_config->pin_d3, camera_config->pin_d2, camera_config->pin_d1, camera_config->pin_d0, camera_config->pin_vsync, camera_config->pin_href, camera_config->pin_pclk, camera_config->xclk_freq_hz, camera_config->ledc_timer, camera_config->ledc_channel, camera_config->pixel_format, camera_config->frame_size, camera_config->jpeg_quality, camera_config->fb_count, camera_config->fb_location, camera_config->grab_mode, camera_config->sccb_i2c_port); + + init_result_ = esp_camera_init(camera_config); + if (init_result_ == ESP_OK) + update_frame(); + else + log_e("Camera initialization failed: 0x%02x", init_result_); + + return init_result_; +} + +esp_err_t micro_rtsp_camera::deinitialize() +{ + return init_result_ == ESP_OK ? esp_camera_deinit() : ESP_OK; +} + +void micro_rtsp_camera::update_frame() +{ + if (fb_) + esp_camera_fb_return(fb_); + + fb_ = esp_camera_fb_get(); +} \ No newline at end of file diff --git a/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp b/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp new file mode 100644 index 0000000..1d20105 --- /dev/null +++ b/lib/micro-rtsp-server/src/micro_rtsp_requests.cpp @@ -0,0 +1,217 @@ +#include + +#include +#include +#include +#include "micro_rtsp_requests.h" + +// https://datatracker.ietf.org/doc/html/rfc2326 + +const std::string micro_rtsp_requests::available_stream_name_ = "/mjpeg/1"; + +bool micro_rtsp_requests::parse_client_port(const std::string &request) +{ + log_v("request: %s", request.c_str()); + + std::regex regex("client_port=([0-9]+)", std::regex_constants::icase); + std::smatch match; + if (!std::regex_match(request, match, regex)) + { + log_e("client_port not found"); + return false; + } + + start_client_port_ = std::stoi(match[1].str()); + return true; +} + +std::string micro_rtsp_requests::handle_rtsp_error(unsigned long cseq, unsigned short code, const std::string &message) +{ + log_e("code: %d, message: %s", code, message.c_str()); + auto now = time(nullptr); + std::ostringstream oss; + oss << "RTSP/1.0 " << code << " " << message << "\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n"; + return oss.str(); +} + +// OPTIONS rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 2 +// User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) +std::string micro_rtsp_requests::handle_options(unsigned long cseq) +{ + auto now = time(nullptr); + std::ostringstream oss; + oss << "RTSP/1.0 200 OK\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" + << "Content-Length: 0\r\n" + << "Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE\r\n" + << "\r\n"; + return oss.str(); +} + +// DESCRIBE rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 3 +// User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) +// Accept: application/sdp +std::string micro_rtsp_requests::handle_describe(unsigned long cseq, const std::string &request) +{ + // Parse the url + static const std::regex regex_url("rtsp:\\/\\/([^\\/:]+)(?::(\\d+))?(\\/.*)?\\s+RTSP\\/1\\.0", std::regex_constants::icase); + std::smatch match; + if (!std::regex_search(request, match, regex_url)) + return handle_rtsp_error(cseq, 400, "Invalid URL"); + + auto host = match[1].str(); + auto port = match[2].str().length() > 0 ? std::stoi(match[2].str()) : 554; + auto path = match[3].str(); + log_i("host: %s, port: %d, path: %s", host.c_str(), port, path.c_str()); + + if (path != available_stream_name_) + return handle_rtsp_error(cseq, 404, "Stream Not Found"); + + std::ostringstream osbody; + osbody << "v=0\r\n" + << "o=- " << std::rand() << " 1 IN IP4 " << host << "\r\n" + << "s=\r\n" + << "t=0 0\r\n" // start / stop - 0 -> unbounded and permanent session + << "m=video 0 RTP/AVP 26\r\n" // currently we just handle UDP sessions + << "c=IN IP4 0.0.0.0\r\n"; + auto body = osbody.str(); + + auto now = time(nullptr); + std::ostringstream oss; + oss << "RTSP/1.0 200 OK\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" + << "Content-Base: rtsp://" << host << ":" << port << path << "/" << "\r\n" + << "Content-Type: application/sdp\r\n" + << "Content-Length: " << body.size() << "\r\n" + << "\r\n" + << body; + return oss.str(); +} + +// SETUP rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 0 +// Transport: RTP/AVP;unicast;client_port=9058-9059 +std::string micro_rtsp_requests::handle_setup(unsigned long cseq, const std::map &lines) +{ + log_v("request: %s", request.c_str()); + + auto it = lines.find("Transport"); + if (it == lines.end()) + return handle_rtsp_error(cseq, 400, "No Transport Header Found"); + + static const std::regex regex_transport("\\s+RTP\\/AVP(\\/TCP)?;unicast;client_port=(\\d+)-(\\d+)", std::regex_constants::icase); + std::smatch match; + if (!std::regex_search(it->second, match, regex_transport)) + return handle_rtsp_error(cseq, 400, "Could Not Parse Transport"); + + tcp_transport_ = match[1].str().length() > 0; + start_client_port_ = std::stoi(match[2].str()); + end_client_port_ = std::stoi(match[3].str()); + log_i("tcp_transport: %d, start_client_port: %d, end_client_port: %d", tcp_transport_, start_client_port_, end_client_port_); + + std::ostringstream ostransport; + if (tcp_transport_) + ostransport << "RTP/AVP/TCP;unicast;interleaved=0-1"; + else + ostransport << "RTP/AVP;unicast;destination=127.0.0.1;source=127.0.0.1;client_port=" << start_client_port_ << "-" << end_client_port_ + 1 << ";server_port=" << rtp_streamer_port_ << "-" << rtp_streamer_port_/*rtcp_streamer_port_*/; + + auto now = time(nullptr); + std::ostringstream oss; + oss << "RTSP/1.0 200 OK\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" + << "Transport: " << ostransport.str() << "\r\n" + << "Session: " << rtsp_session_id_<< "\r\n"; + return oss.str(); +} + +std::string micro_rtsp_requests::handle_play(unsigned long cseq) +{ + log_v("request: %s", request.c_str()); + + stream_active_ = true; + + auto now = time(nullptr); + std::ostringstream oss; + oss << "RTSP/1.0 200 OK\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" + << "Range: npt=0.000-\r\n" + << "Session: " << rtsp_session_id_ << "\r\n" + << "RTP-Info: url=rtsp://127.0.0.1:8554" << available_stream_name_ << "/track1" << "\r\n" + << "\r\n"; + return oss.str(); +} + +std::string micro_rtsp_requests::handle_teardown(unsigned long cseq) +{ + log_v("request: %s", request.c_str()); + + stream_stopped_ = true; + + auto now = time(nullptr); + std::ostringstream oss; + oss << "RTSP/1.0 200 OK\r\n" + << "CSeq: " << cseq << "\r\n" + << std::put_time(std::gmtime(&now), "Date: %a, %b %d %Y %H:%M:%S GMT") << "\r\n" + << "\r\n"; + return oss.str(); +} + +// Parse a request e.g. +// Request: OPTIONS rtsp://192.168.178.247:554/mjpeg/1 RTSP/1.0 +// CSeq: 2 +// User-Agent: LibVLC/3.0.20 (LIVE555 Streaming Media v2016.11.28) + +std::string micro_rtsp_requests::process_request(const std::string &request) +{ + log_v("request: %s", request.c_str()); + + std::stringstream ss(request); + // Get the request line + std::string request_line; + if (!std::getline(ss, request_line)) + return handle_rtsp_error(0, 400, "No Request Found"); + + // Create a map with headers + std::string line; + std::map headers; + std::size_t pos; + while (std::getline(ss, line)) + { + if ((pos = line.find(':')) != std::string::npos) + headers[line.substr(0, pos)] = line.substr(pos + 1); +// else +// log_e("No : found for header: %s", line.c_str()); + } + + log_i("request_line: %s", request_line.c_str()); + for (const auto &header : headers) + log_i("header: %s: %s", header.first.c_str(), header.second.c_str()); + + // Check for CSeq + const auto cseq_it = headers.find("CSeq"); + if (cseq_it == headers.end()) + return handle_rtsp_error(0, 400, "No Sequence Found"); + + auto cseq = std::stoul(cseq_it->second); + + if (request_line.find("OPTIONS") == 0) + return handle_options(cseq); + if (request_line.find("DESCRIBE") == 0) + return handle_describe(cseq, request_line); + if (request_line.find("SETUP") == 0) + return handle_setup(cseq, headers); + if (request_line.find("PLAY") == 0) + return handle_play(cseq); + if (request_line.find("TEARDOWN") == 0) + return handle_teardown(cseq); + + return handle_rtsp_error(cseq, 400, "Unknown Command or malformed request"); +} diff --git a/lib/micro-rtsp-server/src/micro_rtsp_server.cpp b/lib/micro-rtsp-server/src/micro_rtsp_server.cpp new file mode 100644 index 0000000..0028167 --- /dev/null +++ b/lib/micro-rtsp-server/src/micro_rtsp_server.cpp @@ -0,0 +1,108 @@ +#include +#include +#include +#include + +// Check client connections every 100 milliseconds +#define CHECK_CLIENT_INTERVAL 10 + +micro_rtsp_server::micro_rtsp_server(micro_rtsp_source &source) + : source_(source), streamer_(source) +{ +} + +micro_rtsp_server::~micro_rtsp_server() +{ + end(); +} + +void micro_rtsp_server::begin(unsigned short port /*= 554*/) +{ + WiFiServer::begin(port); +} + +void micro_rtsp_server::end() +{ + WiFiServer::end(); +} + +void micro_rtsp_server::loop() +{ + auto now = millis(); + + if (next_check_client_ < now) + { + log_v("Check for new client"); + next_check_client_ = now + CHECK_CLIENT_INTERVAL; + + // Check if a client wants to connect + auto client = accept(); + if (client) + clients_.push_back(rtsp_client(client)); + + // Check for idle clients + clients_.remove_if([](rtsp_client &c) + { return !c.connected(); }); + + for (auto client : clients_) + client.handle_request(); + } + + if (next_frame_update_ < now) + { + log_v("Stream frame t=%d", next_frame_update_); + next_frame_update_ = now + frame_interval_; + + auto ts = time(nullptr); + // Get next jpg frame + source_.update_frame(); + // Decode to get quantitation- and scan data + jpg jpg; + auto jpg_data = source_.data(); + auto jpg_size = source_.size(); + assert(jpg.decode(jpg_data, jpg_size)); + + auto jpg_scan_current = (uint8_t *)jpg.jpeg_data_start; + while (jpg_scan_current < jpg.jpeg_data_end) + { + auto packet = streamer_.create_jpg_packet(jpg.jpeg_data_start, jpg.jpeg_data_end, &jpg_scan_current, ts, jpg.quantization_table_luminance_->data, jpg.quantization_table_chrominance_->data); + for (auto client : clients_) + { + log_i("Stream frame to client: 0x%08x", client); + // RTP over TCP encapsulates in a $ + client.write((const uint8_t *)packet, packet->length + sizeof(rtp_over_tcp_hdr_t)); + // TODO: UDP + } + free(packet); + } + } +} + +micro_rtsp_server::rtsp_client::rtsp_client(const WiFiClient &wifi_client) + : WiFiClient(wifi_client) +{ +} + +micro_rtsp_server::rtsp_client::~rtsp_client() +{ + stop(); +} + +void micro_rtsp_server::rtsp_client::handle_request() +{ + // Read if data available + auto bytes_available = available(); + if (bytes_available > 0) + { + std::string request(bytes_available, '\0'); + if (read((uint8_t *)&request[0], bytes_available) == bytes_available) + { + request.resize(bytes_available); + log_i("Request: %s", request.c_str()); + auto response = process_request(request); + log_i("Response: %s", response.c_str()); + println(response.c_str()); + println(); + } + } +} diff --git a/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp b/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp new file mode 100644 index 0000000..cf49658 --- /dev/null +++ b/lib/micro-rtsp-server/src/micro_rtsp_streamer.cpp @@ -0,0 +1,82 @@ +#include +#include +#include + +#include "micro_rtsp_streamer.h" +#include "esp_random.h" + +micro_rtsp_streamer::micro_rtsp_streamer(const micro_rtsp_source &source) + : source_(source) +{ + // Random number + ssrc_ = esp_random(); + sequence_number_ = 0; +} + +rtp_over_tcp_hdr_t *micro_rtsp_streamer::create_jpg_packet(const uint8_t *jpg_scan, const uint8_t *jpg_scan_end, uint8_t **jpg_offset, const uint32_t timestamp, const uint8_t *quantization_table_luminance, const uint8_t *quantization_table_chrominance) +{ + log_v("jpg_scan:0x%08x, jpg_scan_end:0x%08x, jpg_offset:0x%08x, timestamp:%d, quantization_table_luminance:0x%08x, quantization_table_chrominance:0x%08x", jpg_scan, jpg_scan_end, jpg_offset, timestamp, quantization_table_luminance, quantization_table_chrominance); + + // The MTU of wireless networks is 2,312 bytes. This size includes the packet headers. + const auto isFirstFragment = jpg_scan == *jpg_offset; + const auto include_quantization_tables = isFirstFragment && quantization_table_luminance != nullptr && quantization_table_chrominance != nullptr; + // Quantization tables musty be included in the first packet + const auto headers_size = include_quantization_tables ? sizeof(jpeg_packet_with_quantization_t) : sizeof(jpeg_packet_t); + const auto payload_size = max_wifi_mtu - headers_size; + + const auto jpg_bytes_left = jpg_scan_end - *jpg_offset; + const bool isLastFragment = jpg_bytes_left <= payload_size; + const auto jpg_bytes = isLastFragment ? jpg_bytes_left : payload_size; + const uint16_t packet_size = headers_size + jpg_bytes; + + const auto packet = static_cast(calloc(1, packet_size)); + + // 4 bytes RTP over TCP header + packet->rtp_over_tcp_hdr.channel = 0; + packet->rtp_over_tcp_hdr.length = packet_size; + log_v("rtp_over_tcp_hdr_t={.magic=%c,.channel=%u,.length=%u}", packet->rtp_over_tcp_hdr.magic, packet->rtp_over_tcp_hdr.channel, packet->rtp_over_tcp_hdr.length); + + // 12 bytes RTP header + packet->rtp_hdr.version = 2; + packet->rtp_hdr.marker = isLastFragment; + packet->rtp_hdr.pt = RTP_PAYLOAD_JPG; + packet->rtp_hdr.seq = sequence_number_; + packet->rtp_hdr.ts = timestamp; + packet->rtp_hdr.ssrc = ssrc_; + log_v("rtp_hdr={.version:%u,.padding:%u,.extension:%u,.cc:%u,.marker:%u,.pt:%u,.seq:%u,.ts:%u,.ssrc:%u}", packet->rtp_hdr.version, packet->rtp_hdr.padding, packet->rtp_hdr.extension, packet->rtp_hdr.cc, packet->rtp_hdr.marker, packet->rtp_hdr.pt, packet->rtp_hdr.seq, packet->rtp_hdr.ts, packet->rtp_hdr.ssrc); + + // 8 bytes JPEG payload header + packet->jpeg_hdr.tspec = 0; // type-specific field + packet->jpeg_hdr.off = (uint32_t)(*jpg_offset - jpg_scan); // fragment byte offset (24 bits in jpg) + packet->jpeg_hdr.type = 0; // id of jpeg decoder params + packet->jpeg_hdr.q = (uint8_t)(include_quantization_tables ? 0x80 : 0x5e); // quantization factor (or table id) 5eh=94d + packet->jpeg_hdr.width = (uint8_t)(source_.width() >> 3); // frame width in 8 pixel blocks + packet->jpeg_hdr.height = (uint8_t)(source_.height() >> 3); // frame height in 8 pixel blocks + log_v("jpeg_hdr={.tspec:%u,.off:0x%6x,.type:0x2%x,.q:%u,.width:%u.height:%u}", packet->jpeg_hdr.tspec, packet->jpeg_hdr.off, packet->jpeg_hdr.type, packet->jpeg_hdr.q, packet->jpeg_hdr.width, packet->jpeg_hdr.height); + + // Only in first packet of the frame + if (include_quantization_tables) + { + auto packet_with_quantization = reinterpret_cast(packet); + packet_with_quantization->jpeg_hdr_qtable.mbz = 0; + packet_with_quantization->jpeg_hdr_qtable.precision = 0; // 8 bit precision + packet_with_quantization->jpeg_hdr_qtable.length = jpeg_quantization_table_length + jpeg_quantization_table_length; + log_v("jpeg_hdr_qtable={.mbz:%u,.precision:%u,.length:%u}", packet_with_quantization->jpeg_hdr_qtable.mbz, packet_with_quantization->jpeg_hdr_qtable.precision, packet_with_quantization->jpeg_hdr_qtable.length); + memcpy(packet_with_quantization->quantization_table_luminance, quantization_table_luminance, jpeg_quantization_table_length); + memcpy(packet_with_quantization->quantization_table_chrominance, quantization_table_chrominance, jpeg_quantization_table_length); + // Copy JPG data + memcpy(packet_with_quantization->jpeg_data, *jpg_offset, jpg_bytes); + } + else + { + // Copy JPG data + memcpy(packet->jpeg_data, *jpg_offset, jpg_bytes); + } + + // Update JPG offset + *jpg_offset += jpg_bytes; + // Update sequence number + sequence_number_++; + + return (rtp_over_tcp_hdr_t *)packet; +} \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 3f722ef..52cd65e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -10,7 +10,7 @@ ############################################################################### [platformio] -#default_envs = esp32cam_ai_thinker +default_envs = esp32cam_ai_thinker #default_envs = esp32cam_espressif_esp_eye #default_envs = esp32cam_espressif_esp32s2_cam_board #default_envs = esp32cam_espressif_esp32s2_cam_header @@ -31,23 +31,25 @@ [env] platform = espressif32 framework = arduino +test_framework = unity #upload_protocol = espota #upload_port = 192.168.178.223 #upload_flags = --auth='ESP32CAM-RTSP' # Partition scheme for OTA -board_build.partitions = min_spiffs.csv +#board_build.partitions = max_spiffs.csv monitor_speed = 115200 monitor_rts = 0 monitor_dtr = 0 -monitor_filters = log2file, time, default, esp32_exception_decoder +#monitor_filters = log2file, time, default, esp32_exception_decoder +monitor_filters = esp32_exception_decoder build_flags = -Ofast -D 'BOARD_NAME="${this.board}"' - -D 'CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE' + -D 'CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO' -D 'IOTWEBCONF_PASSWORD_LEN=64' board_build.embed_txtfiles = @@ -56,7 +58,8 @@ board_build.embed_txtfiles = lib_deps = prampec/IotWebConf@^3.2.1 geeksville/Micro-RTSP@^0.1.6 - rzeldent/micro-moustache@^1.0.1 + rzeldent/micro-moustache + rzeldent/micro-timezonedb [env:esp32cam_ai_thinker] board = esp32cam_ai_thinker diff --git a/src/main.cpp b/src/main.cpp index 8899780..2b9cee2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,9 @@ #include #include +#include +#include + // HTML files extern const char index_html_min_start[] asm("_binary_html_index_min_html_start"); @@ -47,11 +50,15 @@ auto param_dcw = iotwebconf::Builder("dcw").labe auto param_colorbar = iotwebconf::Builder("cb").label("Colorbar").defaultValue(DEFAULT_COLORBAR).build(); // Camera -OV2640 cam; +// OV2640 cam; // DNS Server DNSServer dnsServer; // RTSP Server -std::unique_ptr camera_server; +// std::unique_ptr camera_server; + +micro_rtsp_camera camera; +micro_rtsp_server server(camera); + // Web server WebServer web_server(80); @@ -100,7 +107,7 @@ void handle_root() {"Uptime", String(format_duration(millis() / 1000))}, {"FreeHeap", format_memory(ESP.getFreeHeap())}, {"MaxAllocHeap", format_memory(ESP.getMaxAllocHeap())}, - {"NumRTSPSessions", camera_server != nullptr ? String(camera_server->num_connected()) : "RTSP server disabled"}, + {"NumRTSPSessions", String(server.clients())}, // Network {"HostName", hostname}, {"MacAddress", WiFi.macAddress()}, @@ -162,10 +169,10 @@ void handle_snapshot() // Remove old images stored in the frame buffer auto frame_buffers = CAMERA_CONFIG_FB_COUNT; while (frame_buffers--) - cam.run(); + camera.update_frame(); - auto fb_len = cam.getSize(); - auto fb = (const char *)cam.getfb(); + auto fb_len = camera.size(); + auto fb = camera.data(); if (fb == nullptr) { web_server.send(404, "text/plain", "Unable to obtain frame buffer from the camera"); @@ -175,7 +182,7 @@ void handle_snapshot() web_server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); web_server.setContentLength(fb_len); web_server.send(200, "image/jpeg", ""); - web_server.sendContent(fb, fb_len); + web_server.sendContent((const char *)fb, fb_len); } #define STREAM_CONTENT_BOUNDARY "123456789000000000000987654321" @@ -197,11 +204,11 @@ void handle_stream() while (client.connected()) { client.write("\r\n--" STREAM_CONTENT_BOUNDARY "\r\n"); - cam.run(); + camera.update_frame(); client.write("Content-Type: image/jpeg\r\nContent-Length: "); - sprintf(size_buf, "%d\r\n\r\n", cam.getSize()); + sprintf(size_buf, "%d\r\n\r\n", camera.size()); client.write(size_buf); - client.write(cam.getfb(), cam.getSize()); + client.write(camera.data(), camera.size()); } log_v("client disconnected"); @@ -218,7 +225,11 @@ esp_err_t initialize_camera() log_i("JPEG quality: %d", param_jpg_quality.value()); auto jpeg_quality = param_jpg_quality.value(); log_i("Frame duration: %d ms", param_frame_duration.value()); - const camera_config_t camera_config = { + + // Set frame duration + server.set_frame_interval(param_frame_duration.value()); + + camera_config_t camera_config = { .pin_pwdn = CAMERA_CONFIG_PIN_PWDN, // GPIO pin for camera power down line .pin_reset = CAMERA_CONFIG_PIN_RESET, // GPIO pin for camera reset line .pin_xclk = CAMERA_CONFIG_PIN_XCLK, // GPIO pin for camera XCLK line @@ -247,10 +258,12 @@ esp_err_t initialize_camera() #if CONFIG_CAMERA_CONVERTER_ENABLED conv_mode = CONV_DISABLE, // RGB<->YUV Conversion mode #endif - .sccb_i2c_port = SCCB_I2C_PORT // If pin_sccb_sda is -1, use the already configured I2C bus by number + .sccb_i2c_port = CAMERA_CONFIG_SCCB_I2C_PORT // If pin_sccb_sda is -1, use the already configured I2C bus by number }; - return cam.init(camera_config); + return camera.initialize(&camera_config); + + // return cam.init(camera_config); } void update_camera_settings() @@ -289,7 +302,8 @@ void update_camera_settings() void start_rtsp_server() { log_v("start_rtsp_server"); - camera_server = std::unique_ptr(new rtsp_server(cam, param_frame_duration.value(), RTSP_PORT)); + + server.begin(RTSP_PORT); // Add RTSP service to mDNS // HTTP is already set by iotWebConf MDNS.addService("rtsp", "tcp", RTSP_PORT); @@ -374,21 +388,24 @@ void setup() #endif iotWebConf.init(); + // Set the time servers + configTime(0, 0, NTP_SERVERS); + // Try to initialize 3 times for (auto i = 0; i < 3; i++) { + log_i("Initializing camera..."); camera_init_result = initialize_camera(); if (camera_init_result == ESP_OK) - { - update_camera_settings(); break; - } esp_camera_deinit(); - log_e("Failed to initialize camera. Error: 0x%0x. Frame size: %s, frame rate: %d ms, jpeg quality: %d", camera_init_result, param_frame_size.value(), param_frame_duration.value(), param_jpg_quality.value()); + log_e("Failed to initialize camera. Error: 0x%04x. Frame size: %s, frame rate: %d ms, jpeg quality: %d", camera_init_result, param_frame_size.value(), param_frame_duration.value(), param_jpg_quality.value()); delay(500); } + update_camera_settings(); + // Set up required URL handlers on the web server web_server.on("/", HTTP_GET, handle_root); web_server.on("/config", [] @@ -406,6 +423,5 @@ void loop() { iotWebConf.doLoop(); - if (camera_server) - camera_server->doLoop(); + server.loop(); } \ No newline at end of file diff --git a/test/test_main.cpp b/test/test_main.cpp new file mode 100644 index 0000000..289fd2b --- /dev/null +++ b/test/test_main.cpp @@ -0,0 +1,127 @@ +#include +#include +#include + +#include + +#include +#include + +static unsigned char jpeg[8468] = { + // SOI + 0xff, 0xd8, + // APP00 + 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // DQT + 0xff, 0xdb, 0x00, 0x43, 0x00, 0x0e, 0x0a, 0x0b, 0x0c, 0x0b, 0x09, 0x0e, 0x0c, 0x0b, 0x0c, 0x10, 0x0f, 0x0e, 0x11, 0x15, 0x23, 0x17, 0x15, 0x13, 0x13, 0x15, 0x2b, 0x1f, 0x20, 0x19, 0x23, 0x33, 0x2d, 0x35, 0x35, 0x32, 0x2d, 0x31, 0x30, 0x38, 0x3f, 0x51, 0x44, 0x38, 0x3c, 0x4c, 0x3c, 0x30, 0x31, 0x46, 0x5f, 0x47, 0x4c, 0x53, 0x56, 0x5a, 0x5b, 0x5a, 0x36, 0x43, 0x63, 0x6a, 0x62, 0x58, 0x69, 0x51, 0x58, 0x5a, 0x57, + // DQT + 0xff, 0xdb, 0x00, 0x43, 0x01, 0x0f, 0x10, 0x10, 0x15, 0x12, 0x15, 0x29, 0x17, 0x17, 0x29, 0x57, 0x3a, 0x31, 0x3a, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + // DHT + 0xff, 0xc4, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + // DHT + 0xff, 0xc4, 0x00, 0xb5, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 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, + // DHT + 0xff, 0xc4, 0x00, 0x1f, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + // DHT + 0xff, 0xc4, 0x00, 0xb5, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 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, + // SOF + 0xff, 0xc0, 0x00, 0x11, 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, + // SOS + 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, + // SOF7 + 0xe0, 0xc7, 0xd6, 0x91, 0xb8, 0xae, 0x9d, 0x6e, 0x02, 0xf3, 0xcf, 0x14, 0x87, 0x93, 0x48, 0x61, 0xec, 0x29, 0x7a, 0x8a, 0x77, 0x01, 0x07, 0xbd, 0x2d, 0x16, 0xd0, 0x42, 0x67, 0x8a, 0x52, 0x3d, 0x29, 0x0c, 0x4c, 0xd0, 0x28, 0x10, 0x94, 0x67, 0x9a, 0x90, 0x0f, 0xa9, 0xa2, 0xa1, 0x80, 0x1c, 0xf6, 0xa4, 0xe6, 0x95, 0xd8, 0x07, 0x22, 0x8a, 0xa1, 0x05, 0x25, 0x3b, 0x08, 0x3a, 0xd1, 0xc5, 0x46, 0xa5, 0x05, 0x1e, 0xf4, 0x05, 0x83, 0xeb, 0x45, 0x20, 0x0a, 0x29, 0x80, 0x94, 0x53, 0xb9, 0x23, 0x7b, 0xd3, 0xa9, 0x5c, 0x62, 0x52, 0xd2, 0xb7, 0x50, 0x13, 0xb5, 0x2f, 0xd2, 0x8b, 0x0c, 0x4a, 0x2a, 0xc0, 0x28, 0xa8, 0x01, 0x0d, 0x2d, 0x02, 0xb0, 0x1a, 0x28, 0x00, 0xa4, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xcd, 0x3b, 0x00, 0x51, 0x48, 0x02, 0x92, 0x80, 0x0a, 0x29, 0x8d, 0x8b, 0x45, 0x21, 0x05, 0x25, 0x26, 0xc4, 0x14, 0x53, 0x1a, 0x0a, 0x28, 0x01, 0x29, 0x69, 0x30, 0x0a, 0x29, 0x8c, 0x28, 0xa6, 0x20, 0xa2, 0x95, 0xc0, 0x28, 0xa0, 0x61, 0x49, 0x48, 0x41, 0x4b, 0x55, 0x6d, 0x40, 0x9e, 0x90, 0x74, 0xfb, 0xbc, 0xd6, 0xbe, 0x85, 0xb6, 0x3b, 0xb5, 0x25, 0x4f, 0x28, 0x85, 0xe3, 0xbd, 0x27, 0x5a, 0xab, 0x00, 0xb4, 0x7d, 0x4d, 0x24, 0x21, 0xb9, 0x3c, 0x53, 0xb3, 0xf9, 0xd3, 0xea, 0x02, 0x0a, 0x3d, 0xe8, 0xf3, 0x00, 0xa3, 0x1c, 0x73, 0x4a, 0xe0, 0x27, 0x4e, 0x94, 0x95, 0x31, 0xdc, 0x10, 0xb4, 0x74, 0xa0, 0x5d, 0x42, 0x93, 0xbd, 0x00, 0x03, 0xbd, 0x1d, 0xe8, 0xbe, 0xa2, 0x13, 0x22, 0x8a, 0x43, 0x03, 0xed, 0x45, 0x00, 0x25, 0x2d, 0x21, 0xdc, 0x28, 0xa0, 0x42, 0x76, 0xa2, 0x98, 0x82, 0x8a, 0x82, 0x83, 0xb5, 0x25, 0x55, 0xc4, 0x2d, 0x25, 0x20, 0x0a, 0x2a, 0x80, 0x28, 0xa4, 0xd0, 0x05, 0x14, 0xba, 0x00, 0x51, 0x4d, 0x0c, 0x4a, 0x28, 0x10, 0x51, 0x48, 0x00, 0xd2, 0x53, 0x01, 0xd4, 0x95, 0x3b, 0x0c, 0x4a, 0x5a, 0xab, 0xe8, 0x01, 0x49, 0x48, 0x02, 0x96, 0x81, 0x09, 0x4b, 0x40, 0xc2, 0x92, 0x80, 0x0a, 0x28, 0x10, 0x52, 0x52, 0x01, 0x68, 0xaa, 0x4c, 0x02, 0x8a, 0x4c, 0x61, 0x49, 0x40, 0x85, 0xa4, 0xa0, 0x62, 0xd2, 0x50, 0xc0, 0x28, 0xa6, 0x04, 0xfd, 0x39, 0xa5, 0x23, 0xb1, 0xad, 0xb6, 0x29, 0x89, 0xcd, 0x2e, 0x72, 0x39, 0xa3, 0xa8, 0xb7, 0x17, 0x3b, 0x47, 0x19, 0xa3, 0xee, 0xd0, 0xb6, 0x0f, 0x20, 0x14, 0x50, 0xdf, 0x40, 0x13, 0xbd, 0x15, 0x1c, 0xc2, 0xd8, 0x4a, 0x75, 0x00, 0x27, 0x38, 0xa4, 0xcd, 0x3f, 0x30, 0x0a, 0x4a, 0x3a, 0x80, 0x51, 0x4a, 0xdd, 0x44, 0x14, 0x94, 0xb7, 0x43, 0x0c, 0xd2, 0x9a, 0x04, 0x27, 0x1d, 0xa9, 0x4f, 0x4a, 0x81, 0x8d, 0xa5, 0xaa, 0xb3, 0x60, 0x1d, 0x29, 0x28, 0x42, 0x0c, 0xd1, 0x54, 0x30, 0xea, 0x28, 0x3d, 0x6a, 0x40, 0x28, 0xa4, 0x21, 0x28, 0xa5, 0x61, 0x0b, 0x49, 0xda, 0x99, 0x41, 0x47, 0xb5, 0x02, 0x0a, 0x4a, 0x18, 0x5c, 0x28, 0xa6, 0x21, 0x45, 0x25, 0x41, 0x42, 0xd2, 0x55, 0x08, 0x4a, 0x29, 0x00, 0xb4, 0x50, 0x01, 0x45, 0x08, 0x62, 0x51, 0x4c, 0x42, 0xd1, 0x4a, 0xe0, 0x36, 0x96, 0x9b, 0x06, 0x06, 0x81, 0x40, 0xec, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x12, 0x96, 0x98, 0x82, 0x92, 0x80, 0x0a, 0x2a, 0x40, 0x28, 0xa6, 0x30, 0xa5, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x2d, 0x0c, 0x44, + // DATA + 0xff, 0x00, 0xef, 0x50, 0x79, 0xf6, 0xad, 0xca, 0x02, 0x4e, 0x68, 0xce, 0x3f, 0x1a, 0x3a, 0x00, 0x52, 0x9a, 0x00, 0x4a, 0x3b, 0x73, 0x49, 0x5c, 0x4c, 0x28, 0xe3, 0x27, 0x8a, 0x6f, 0xde, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x56, 0x00, 0xcd, 0x14, 0x00, 0x9d, 0x0d, 0x2d, 0x20, 0x12, 0x93, 0xa5, 0x00, 0x1f, 0x4a, 0x3b, 0x54, 0x5c, 0x03, 0xaf, 0x5a, 0x28, 0xbe, 0x80, 0x14, 0x52, 0x00, 0x14, 0x94, 0xc5, 0x60, 0xef, 0x49, 0x4f, 0xcc, 0x2e, 0x2d, 0x14, 0x6e, 0x21, 0x05, 0x2d, 0x21, 0x89, 0xde, 0x8a, 0x43, 0x0a, 0x3b, 0x55, 0x31, 0x05, 0x25, 0x48, 0x05, 0x2d, 0x30, 0xb0, 0x51, 0x48, 0x62, 0x51, 0x54, 0x21, 0x45, 0x25, 0x48, 0x05, 0x25, 0x00, 0x2d, 0x1d, 0xe9, 0x80, 0x51, 0x40, 0x09, 0x45, 0x00, 0x14, 0x52, 0x01, 0x29, 0x69, 0xb6, 0x02, 0x50, 0x28, 0x18, 0xb4, 0x54, 0x88, 0x28, 0xaa, 0x01, 0x29, 0x69, 0x0c, 0x4a, 0x29, 0x80, 0xb4, 0x95, 0x22, 0x16, 0x8a, 0x06, 0x25, 0x2d, 0x50, 0x84, 0xa2, 0xa4, 0x02, 0x8a, 0xa0, 0x27, 0xe3, 0x34, 0xbf, 0x4a, 0xd7, 0x52, 0xac, 0x1d, 0xa8, 0xcf, 0xcb, 0x46, 0xa1, 0x71, 0x39, 0xa7, 0x52, 0x60, 0x27, 0x7c, 0x51, 0xda, 0x85, 0x27, 0xb0, 0x05, 0x27, 0x6a, 0x42, 0x0a, 0x28, 0xdc, 0x42, 0x52, 0xf5, 0xa6, 0xf4, 0x18, 0x9f, 0x5a, 0x3b, 0xd2, 0xbd, 0xc0, 0x28, 0xa9, 0x00, 0xa4, 0xcd, 0x35, 0xb8, 0x00, 0xa2, 0x95, 0x80, 0x4e, 0xd4, 0x53, 0x5d, 0x80, 0x07, 0x5a, 0x5a, 0x5d, 0x44, 0x14, 0x94, 0x0c, 0x28, 0xa4, 0x48, 0x76, 0xa4, 0xa7, 0xe6, 0x50, 0x51, 0x52, 0x84, 0x14, 0x53, 0xb0, 0x09, 0x4b, 0x52, 0x02, 0x52, 0xd3, 0x01, 0x33, 0x41, 0xa1, 0x00, 0x51, 0x4c, 0x62, 0x51, 0x53, 0x60, 0x0a, 0x5a, 0xa1, 0x05, 0x14, 0xac, 0x21, 0x29, 0x68, 0x28, 0x4a, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x00, 0x28, 0xa6, 0x31, 0x29, 0x69, 0x88, 0x4a, 0x28, 0x01, 0x68, 0xa4, 0x21, 0x29, 0x68, 0x18, 0x94, 0xb4, 0x6e, 0x31, 0x28, 0xa4, 0x20, 0xa2, 0x98, 0xc2, 0x96, 0x90, 0x84, 0xa2, 0x80, 0x0a, 0x28, 0x02, 0x7a, 0x3d, 0xc5, 0x6e, 0x8a, 0x0a, 0x32, 0xdd, 0xcd, 0x2f, 0x21, 0x8a, 0x7a, 0x8a, 0x5e, 0xf4, 0xed, 0xa5, 0xc9, 0x10, 0x52, 0x7f, 0x0d, 0x48, 0xc3, 0x14, 0xa0, 0xe4, 0x50, 0xc4, 0x14, 0x53, 0xb8, 0x86, 0xd2, 0xfd, 0x69, 0x75, 0x18, 0x94, 0x52, 0x00, 0xcd, 0x25, 0x56, 0xc0, 0x2d, 0x1d, 0xba, 0xd4, 0x30, 0x0a, 0x4a, 0x60, 0x14, 0x94, 0xae, 0x02, 0xd1, 0x40, 0x84, 0xa2, 0x90, 0xc2, 0x92, 0x98, 0x82, 0x8e, 0xb4, 0x98, 0x05, 0x14, 0xac, 0x01, 0x45, 0x00, 0x14, 0x95, 0x40, 0x1d, 0xa8, 0xa4, 0x02, 0xd2, 0x51, 0x60, 0x0a, 0x28, 0xd8, 0x6c, 0x29, 0x69, 0x08, 0x4a, 0x4a, 0x18, 0x0b, 0x49, 0x40, 0x05, 0x14, 0x75, 0x00, 0xa2, 0x90, 0x05, 0x2d, 0x36, 0xc0, 0x29, 0x28, 0x40, 0x14, 0x50, 0x01, 0x49, 0x4c, 0x02, 0x96, 0x90, 0xc2, 0x8a, 0x42, 0x12, 0x94, 0xd1, 0xd4, 0x04, 0xa2, 0x98, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x00, 0x14, 0x53, 0xb8, 0x09, 0x4b, 0x53, 0x61, 0x96, 0x0f, 0xe9, 0x4b, 0xf8, 0x56, 0xe3, 0x7f, 0x10, 0x9e, 0xbe, 0x94, 0x63, 0x1d, 0x69, 0xd8, 0xa0, 0xf7, 0xa4, 0xa9, 0x49, 0x80, 0xb8, 0xa3, 0xb5, 0x1b, 0xb2, 0x58, 0x94, 0xbf, 0x51, 0x40, 0x84, 0x1e, 0xf4, 0x51, 0xb8, 0x09, 0xd6, 0x97, 0x15, 0x2c, 0x41, 0x49, 0x48, 0x61, 0x49, 0xd2, 0xa8, 0x04, 0xef, 0x4b, 0x54, 0xed, 0xb0, 0x85, 0xa4, 0xac, 0xc6, 0x21, 0xa5, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x27, 0x6a, 0xab, 0x80, 0xa2, 0x8a, 0x57, 0x24, 0x4a, 0x4a, 0x2c, 0x31, 0x7f, 0x9d, 0x1d, 0x68, 0x00, 0xa4, 0xa4, 0x31, 0x69, 0x3b, 0xd2, 0x10, 0xb4, 0x94, 0x5c, 0x04, 0xa5, 0xa0, 0x62, 0x52, 0xd5, 0x00, 0x51, 0x48, 0x56, 0x0f, 0xa5, 0x25, 0x20, 0x17, 0x34, 0x51, 0xb0, 0xec, 0x25, 0x14, 0x84, 0x1c, 0x51, 0x4c, 0x02, 0x8a, 0x77, 0x18, 0x51, 0x48, 0x42, 0x52, 0xd2, 0x01, 0x28, 0xa6, 0x01, 0x45, 0x00, 0x2d, 0x25, 0x2e, 0xa2, 0x0a, 0x29, 0xb1, 0x85, 0x14, 0x86, 0x14, 0x53, 0x10, 0x51, 0x4a, 0xe3, 0x0a, 0x28, 0x00, 0xa2, 0xa8, 0x02, 0x8a, 0x40, 0x58, 0xcf, 0xd2, 0x92, 0xb7, 0xe8, 0x31, 0x69, 0x33, 0xc7, 0x3d, 0x2a, 0x53, 0xd4, 0x63, 0xb8, + 0xff, 0x00, 0x22, 0x8e, 0xf5, 0x4f, 0x41, 0x07, 0x6c, 0xd1, 0x53, 0xd0, 0x06, 0xd1, 0x49, 0x00, 0x6e, 0xf4, 0xa2, 0xa9, 0x08, 0x4a, 0x5f, 0x6a, 0x18, 0x08, 0x68, 0x3d, 0x6b, 0x30, 0x0a, 0x2a, 0x56, 0x82, 0x0a, 0x4a, 0xa1, 0x8b, 0x49, 0x40, 0x05, 0x27, 0x6a, 0x37, 0x24, 0x28, 0xa9, 0x18, 0x0a, 0x4e, 0xf4, 0xc6, 0x2d, 0x14, 0x08, 0x4a, 0x29, 0x00, 0x51, 0x4d, 0x8e, 0xc1, 0x49, 0x40, 0x07, 0x7a, 0x28, 0x10, 0x51, 0x4b, 0xcc, 0x61, 0x45, 0x00, 0x14, 0x53, 0xea, 0x01, 0x45, 0x2b, 0x80, 0x94, 0xb4, 0xc0, 0x4a, 0x2a, 0x58, 0x05, 0x14, 0xc1, 0x85, 0x14, 0x00, 0x51, 0x40, 0x84, 0xa5, 0xa0, 0x61, 0x45, 0x0c, 0x02, 0x92, 0x80, 0x0a, 0x29, 0x08, 0x28, 0xa0, 0x61, 0x4b, 0x40, 0x84, 0xa2, 0x81, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x53, 0x42, 0x0a, 0x4a, 0x06, 0x58, 0xcf, 0x34, 0x56, 0xa3, 0x03, 0xeb, 0x4b, 0xcf, 0xa5, 0x02, 0x0c, 0xfa, 0xf5, 0xa5, 0xa7, 0xd0, 0x62, 0x0f, 0x94, 0x60, 0xf5, 0xf6, 0xa2, 0x90, 0x07, 0xbf, 0x14, 0x9d, 0x0e, 0x69, 0x08, 0x4c, 0xfc, 0xb8, 0xed, 0x46, 0x45, 0x56, 0xc1, 0xd0, 0x77, 0xd2, 0x92, 0xa1, 0x82, 0x13, 0xde, 0x8e, 0xf4, 0xc0, 0x4f, 0xc6, 0x97, 0xa5, 0x26, 0x01, 0x9a, 0x4a, 0x00, 0x3b, 0x62, 0x93, 0x8a, 0x00, 0x3a, 0x51, 0x43, 0x10, 0x51, 0xd6, 0x95, 0x80, 0x33, 0x49, 0x48, 0x02, 0x8a, 0x40, 0x14, 0x53, 0xb5, 0x86, 0x1e, 0xf4, 0x53, 0x00, 0x14, 0x94, 0x80, 0x5a, 0x4a, 0x56, 0x00, 0xa2, 0x99, 0x21, 0x45, 0x00, 0x14, 0x50, 0xd0, 0xc4, 0xa2, 0x90, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x90, 0x82, 0x92, 0xa8, 0x05, 0xa2, 0x90, 0xc2, 0x92, 0x84, 0x20, 0xa2, 0x81, 0x85, 0x2d, 0x20, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x53, 0x18, 0x52, 0x52, 0x04, 0x2d, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x02, 0x7f, 0xe7, 0x49, 0x5b, 0xdf, 0xa1, 0x43, 0x85, 0x14, 0x84, 0xc3, 0x14, 0x77, 0xaa, 0xb8, 0xfa, 0x09, 0xed, 0x4b, 0xf5, 0xa5, 0x61, 0x58, 0x4a, 0x05, 0x24, 0x98, 0x07, 0x6a, 0x4a, 0x4c, 0x04, 0xcd, 0x2d, 0x16, 0x00, 0xa4, 0xa2, 0xfa, 0x00, 0x51, 0x4e, 0xf7, 0x06, 0x14, 0x66, 0x93, 0x01, 0x29, 0x7b, 0x54, 0xb0, 0x12, 0x8a, 0x04, 0x14, 0x1a, 0x2c, 0x30, 0xa2, 0x95, 0x84, 0x25, 0x19, 0xa6, 0x30, 0xa2, 0xa5, 0xea, 0x02, 0x52, 0xd0, 0x80, 0x4c, 0xd1, 0x4c, 0x02, 0x8a, 0x56, 0xd0, 0x02, 0x8a, 0x62, 0x0a, 0x29, 0x0c, 0x29, 0x28, 0x10, 0x51, 0x54, 0x01, 0x45, 0x21, 0x85, 0x2d, 0x48, 0x84, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x94, 0xa6, 0xa8, 0x04, 0xa5, 0xa0, 0x04, 0xa2, 0x90, 0x82, 0x8a, 0x06, 0x14, 0x52, 0x00, 0xa2, 0x98, 0x05, 0x14, 0xac, 0x21, 0x29, 0x69, 0x80, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x4a, 0x28, 0x10, 0x51, 0x48, 0x61, 0x4b, 0x42, 0x11, 0x3f, 0xae, 0x3f, 0x3c, 0x52, 0x0e, 0xb5, 0xd2, 0xf4, 0x2c, 0x77, 0x1d, 0xe9, 0x3d, 0xfb, 0xd4, 0xfc, 0x44, 0x8b, 0xef, 0x47, 0x7a, 0x4c, 0x62, 0x52, 0xd3, 0x60, 0xc3, 0xbd, 0x25, 0x17, 0x10, 0x99, 0xe3, 0xa5, 0x29, 0xa9, 0x01, 0x28, 0xa0, 0x02, 0x8e, 0xf5, 0x20, 0xc4, 0xa2, 0x9d, 0xc0, 0x3b, 0x51, 0xde, 0x86, 0x21, 0x3a, 0x52, 0xd2, 0xb0, 0xc2, 0x8a, 0x91, 0x09, 0x45, 0x50, 0xee, 0x25, 0x2d, 0x26, 0x24, 0xc4, 0xa2, 0x98, 0xc2, 0x8a, 0x01, 0x85, 0x02, 0x81, 0x05, 0x25, 0x48, 0x09, 0x4b, 0x4d, 0xea, 0x30, 0xa2, 0x95, 0xc4, 0x14, 0x50, 0xc0, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x08, 0x29, 0x29, 0x8c, 0x29, 0x69, 0x08, 0x28, 0xa0, 0x02, 0x92, 0x81, 0x85, 0x14, 0x00, 0xb4, 0x94, 0x80, 0x5a, 0x4a, 0x60, 0x14, 0x94, 0x00, 0xb4, 0x52, 0x00, 0xa4, 0xaa, 0x01, 0x68, 0xa9, 0x10, 0x51, 0x4c, 0x61, 0x49, 0x48, 0x02, 0x96, 0x81, 0x05, 0x25, 0x03, 0x16, 0x8a, 0x60, 0x4d, 0x47, 0xd0, 0xf1, 0x5b, 0xee, 0x01, 0x9a, 0x5e, 0x3d, 0x39, 0xa4, 0xd1, 0x42, + 0xff, 0x00, 0xbc, 0x0d, 0x26, 0x7d, 0x72, 0x4d, 0x16, 0x10, 0x51, 0xdb, 0xaf, 0xe1, 0x45, 0x98, 0x80, 0xfb, 0xd1, 0xde, 0x93, 0x77, 0x00, 0xa2, 0x92, 0xb0, 0x0d, 0xa5, 0xa0, 0x02, 0x9b, 0x53, 0xb0, 0x0b, 0x45, 0x0f, 0x50, 0x12, 0x96, 0x9f, 0x51, 0x09, 0x4b, 0x40, 0xc4, 0xa4, 0xa9, 0x01, 0x68, 0xa2, 0xe2, 0x12, 0x8a, 0x60, 0x14, 0x52, 0xb8, 0xc4, 0xa2, 0x98, 0x82, 0x96, 0xa4, 0x04, 0xa2, 0x80, 0x0a, 0x29, 0xa1, 0x85, 0x14, 0xee, 0x20, 0xa4, 0xa9, 0x10, 0xb4, 0x94, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x3a, 0x80, 0x51, 0x54, 0x02, 0x51, 0x52, 0x31, 0x68, 0xa4, 0x20, 0xa2, 0x80, 0x12, 0x8a, 0xa0, 0x0a, 0x29, 0x0c, 0x28, 0xa6, 0x21, 0x29, 0x69, 0x00, 0x51, 0x48, 0x02, 0x92, 0xa8, 0x62, 0xd1, 0x52, 0x02, 0x51, 0x4c, 0x02, 0x96, 0x93, 0x10, 0x94, 0x50, 0x01, 0x45, 0x31, 0x8b, 0x49, 0x48, 0x0b, 0x14, 0x71, 0xda, 0xba, 0x2f, 0xa8, 0xb5, 0x13, 0xf0, 0xa0, 0x03, 0x4b, 0x41, 0x80, 0xfa, 0x73, 0x4e, 0x34, 0xdf, 0x98, 0x58, 0x4c, 0x77, 0xa4, 0xa0, 0x61, 0x4b, 0xd2, 0x96, 0x9b, 0x08, 0x29, 0x31, 0xcf, 0x15, 0x28, 0x40, 0x7a, 0x51, 0x49, 0xa1, 0x85, 0x26, 0x79, 0xa7, 0x60, 0xdc, 0x33, 0xed, 0x49, 0x49, 0x21, 0x05, 0x2d, 0x48, 0x09, 0x45, 0x31, 0x05, 0x15, 0x23, 0x0a, 0x4a, 0x43, 0x0a, 0x4a, 0xae, 0xa2, 0x16, 0x92, 0x98, 0x0b, 0x45, 0x20, 0x13, 0xa5, 0x14, 0x00, 0x51, 0x40, 0x0b, 0x49, 0x48, 0x04, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0xd2, 0xa4, 0x61, 0x45, 0x31, 0x06, 0x68, 0xa0, 0x62, 0x51, 0x4c, 0x41, 0x4b, 0x43, 0x00, 0xa4, 0xa4, 0x01, 0x45, 0x16, 0x18, 0x51, 0x48, 0x41, 0x45, 0x17, 0x00, 0xa2, 0x98, 0x05, 0x14, 0x80, 0x28, 0xa6, 0x08, 0x4a, 0x29, 0x0c, 0x5a, 0x4a, 0xa4, 0x20, 0xa2, 0x90, 0x05, 0x2d, 0x20, 0x12, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x00, 0x58, 0xf7, 0x34, 0x0a, 0xe8, 0x4b, 0xb8, 0x07, 0x7a, 0x1b, 0x35, 0x25, 0x59, 0x0b, 0xda, 0x90, 0x50, 0xd9, 0x22, 0xd1, 0xd3, 0xad, 0x08, 0x63, 0x7e, 0x94, 0xb4, 0x48, 0x57, 0x0e, 0x94, 0x94, 0x90, 0x85, 0xa4, 0xfc, 0x31, 0x4b, 0x71, 0x85, 0x25, 0x00, 0x2d, 0x25, 0x2f, 0x31, 0x09, 0x47, 0x5a, 0x63, 0x0a, 0x0d, 0x48, 0x09, 0x4b, 0x4c, 0x02, 0x92, 0xa5, 0x08, 0x28, 0xcd, 0x30, 0x0a, 0x2a, 0x6f, 0x70, 0x0a, 0x4a, 0xa0, 0x0a, 0x28, 0x40, 0x14, 0x50, 0x01, 0x49, 0x48, 0x05, 0xa4, 0xa6, 0x01, 0x45, 0x21, 0x85, 0x14, 0x5c, 0x41, 0x45, 0x31, 0x85, 0x14, 0x84, 0x14, 0x94, 0xc0, 0x29, 0x68, 0x01, 0x28, 0xa4, 0x01, 0xde, 0x8a, 0x06, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0xb8, 0x82, 0x8a, 0x00, 0x29, 0x28, 0x18, 0xb4, 0x94, 0x08, 0x5a, 0x4a, 0x00, 0x28, 0xa6, 0x01, 0x4b, 0x48, 0x62, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x13, 0x9e, 0x28, 0xae, 0x9d, 0xc0, 0x76, 0x3b, 0x75, 0xa4, 0x1c, 0x74, 0xac, 0xb6, 0x1e, 0xe1, 0xf5, 0xa3, 0xad, 0x34, 0x20, 0xa3, 0x8e, 0xd5, 0x43, 0x13, 0xbd, 0x28, 0xa0, 0x42, 0x52, 0x51, 0xa0, 0xc2, 0x8a, 0x97, 0xdc, 0x42, 0xf7, 0xa2, 0xa4, 0x42, 0x51, 0x4c, 0x02, 0x92, 0x90, 0x05, 0x27, 0x7a, 0x00, 0x29, 0x69, 0x00, 0x94, 0x66, 0x98, 0x82, 0x93, 0x14, 0x0c, 0x5a, 0x4a, 0x2e, 0x31, 0x69, 0x29, 0x5c, 0x41, 0x45, 0x03, 0x0a, 0x4a, 0x40, 0x2d, 0x25, 0x21, 0x05, 0x14, 0xc0, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x01, 0x29, 0x69, 0x0c, 0x4a, 0x29, 0xbd, 0x44, 0x14, 0x53, 0x00, 0xa2, 0xa4, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x4a, 0x40, 0x2d, 0x25, 0x02, 0x16, 0x8a, 0x00, 0x29, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0xc4, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0x48, 0x09, 0xcd, 0x19, 0xcf, 0xb5, 0x6c, 0x3b, 0x0b, 0xc6, 0x39, 0xa0, 0x9e, 0x6a, 0x6c, 0x0c, 0x4e, 0xb4, 0xbc, 0x77, 0xab, 0xf2, 0x18, 0x7b, 0x8a, 0x29, 0x08, 0x4a, 0x28, 0x00, 0xe3, 0x3c, 0xd0, 0x3d, 0xe9, 0x00, 0x51, 0xd6, 0x9d, 0xec, 0x21, 0x28, 0xa8, 0x63, 0x0a, 0x42, 0x7d, 0x69, 0x21, 0x05, 0x14, 0x00, 0x52, 0x53, 0xf3, 0x01, 0x69, 0x29, 0x74, 0x18, 0x51, 0x4e, 0xcc, 0x41, 0x45, 0x00, 0x82, 0x92, 0x81, 0x8b, 0x45, 0x40, 0x09, 0x45, 0x50, 0x98, 0x94, 0x50, 0xc1, 0x0b, 0x49, 0x52, 0x01, 0x45, 0x03, 0x0a, 0x4a, 0x60, 0x14, 0xb4, 0xc0, 0x4a, 0x29, 0x00, 0x52, 0xd0, 0x01, 0x49, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa2, 0xe3, 0x0a, 0x29, 0x08, 0x28, 0xa0, 0x02, 0x92, 0x98, 0xc5, 0xa2, 0x95, 0x80, 0x4a, 0x28, 0x01, 0x68, 0xa0, 0x04, 0xa2, 0x80, 0x0a, 0x29, 0x88, 0x28, 0xa4, 0x01, 0x45, 0x00, 0x14, 0x51, 0x61, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x09, 0xe8, 0xef, 0xed, 0x5b, 0x96, 0x2f, 0x1e, 0x99, 0xa3, 0x8a, 0x57, 0x00, 0xa2, 0x9e, 0x9d, 0x45, 0x60, 0xf7, 0xc5, 0x2f, 0x3f, 0x4a, 0x91, 0x0d, 0xfc, 0x28, 0xa6, 0x01, 0x45, 0x21, 0xa1, 0x3b, 0xd1, 0x48, 0x41, 0x47, 0x5a, 0x4c, 0x02, 0x86, 0xc6, 0x6a, 0x6c, 0x20, 0xa4, 0xaa, 0x00, 0xa3, 0x35, 0x23, 0x12, 0x8a, 0xa0, 0x0a, 0x4a, 0x9b, 0x88, 0x5a, 0x2a, 0xae, 0x31, 0x28, 0x34, 0xac, 0x84, 0x14, 0x53, 0x18, 0x51, 0x52, 0xc4, 0x14, 0x50, 0x24, 0x25, 0x14, 0xb7, 0x18, 0x51, 0x43, 0x18, 0x51, 0x4c, 0x02, 0x8a, 0x42, 0x0a, 0x4a, 0x06, 0x14, 0x53, 0xb8, 0x82, 0x8a, 0x43, 0x0a, 0x29, 0x88, 0x28, 0xa0, 0x02, 0x8a, 0x06, 0x25, 0x2d, 0x00, 0x25, 0x14, 0x80, 0x5a, 0x4a, 0x04, 0x14, 0x53, 0x00, 0xa5, 0xa4, 0x02, 0x51, 0x40, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x94, 0xb4, 0x0c, 0x28, 0xa0, 0x09, 0xe9, 0x47, 0x4a, 0xd9, 0x26, 0x0c, 0x4e, 0x29, 0x69, 0x94, 0x18, 0xf4, 0xa4, 0xa5, 0x70, 0xb8, 0xb4, 0x62, 0x91, 0x22, 0x51, 0x4f, 0x60, 0x17, 0xda, 0x9b, 0xea, 0x45, 0x00, 0x29, 0xa2, 0xa3, 0xa8, 0x09, 0x45, 0x27, 0xb8, 0x05, 0x25, 0x3b, 0xd8, 0x42, 0x8a, 0x29, 0x75, 0x18, 0x86, 0x83, 0x47, 0x90, 0x09, 0x45, 0x17, 0x10, 0x51, 0x49, 0x0c, 0x28, 0xa7, 0x64, 0x21, 0x3a, 0x8a, 0x2a, 0x46, 0x14, 0x55, 0x00, 0x51, 0x48, 0x42, 0x52, 0xe6, 0x81, 0x89, 0x45, 0x20, 0x0a, 0x28, 0x00, 0xa4, 0xa6, 0x01, 0x4b, 0x4c, 0x42, 0x51, 0x48, 0x61, 0x47, 0x7a, 0x40, 0x14, 0x50, 0x01, 0x45, 0x30, 0x0a, 0x29, 0x80, 0x51, 0x48, 0x04, 0xa5, 0xa0, 0x41, 0x49, 0x40, 0x0b, 0x45, 0x20, 0x0a, 0x4a, 0x06, 0x14, 0xb4, 0x00, 0x94, 0x53, 0x10, 0x51, 0x48, 0x02, 0x8a, 0x63, 0x12, 0x96, 0x90, 0x05, 0x25, 0x02, 0x16, 0x8a, 0x2e, 0x30, 0xa2, 0x80, 0x45, 0x8a, 0x4a, 0xda, 0xe5, 0x06, 0x29, 0x68, 0x24, 0x28, 0xa0, 0x62, 0x7f, 0x4a, 0x5a, 0x00, 0x5f, 0xc6, 0x9b, 0xf8, 0x54, 0x8a, 0xe1, 0xd2, 0x8e, 0x28, 0x40, 0x14, 0x99, 0xa9, 0xf3, 0x00, 0xa2, 0x81, 0x01, 0xef, 0x49, 0x4c, 0x61, 0x45, 0x01, 0x70, 0xa4, 0xa4, 0x01, 0x45, 0x31, 0x05, 0x15, 0x00, 0x25, 0x15, 0x48, 0x61, 0x45, 0x20, 0x0a, 0x29, 0x88, 0x4a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x06, 0x2d, 0x14, 0x00, 0x94, 0x52, 0xb0, 0x0b, 0x45, 0x21, 0x09, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x42, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x00, 0x5a, 0x4a, 0x06, 0x14, 0xb4, 0x00, 0x94, 0x53, 0x10, 0x51, 0x48, 0x02, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x08, 0x41, 0x45, 0x03, 0x0a, 0x4a, 0x00, 0x5a, 0x29, 0x80, 0x94, 0x52, 0x10, 0x52, 0xd0, 0x02, 0x51, 0x42, 0x19, 0x63, 0xf0, 0xa3, 0x8a, 0xd9, 0x68, 0x86, 0x03, 0x34, 0xb4, 0x86, 0xc4, 0xa2, 0x84, 0x98, 0xba, 0x8b, 0xda, 0x8e, 0xd4, 0x00, 0x52, 0x53, 0x62, 0x0a, 0x2a, 0x76, 0x00, 0xa4, 0xc5, 0x00, 0x14, 0x94, 0x00, 0x51, 0x52, 0x20, 0xa4, 0xaa, 0x43, 0x17, 0xa7, 0xbd, 0x14, 0x79, 0x80, 0x94, 0x54, 0x88, 0x29, 0x28, 0x18, 0xb4, 0x94, 0x08, 0x28, 0xa2, 0xe3, 0x0a, 0x28, 0x15, 0x84, 0xa2, 0x93, 0x00, 0xa2, 0x95, 0xc0, 0x28, 0xa0, 0x02, 0x92, 0xaa, 0xe3, 0x16, 0x93, 0x34, 0x98, 0x85, 0xa4, 0xa0, 0x02, 0x96, 0x90, 0x09, 0x45, 0x31, 0x85, 0x14, 0x08, 0x29, 0x29, 0x00, 0x52, 0xd0, 0x02, 0x51, 0x4f, 0xa0, 0xc2, 0x96, 0x90, 0x05, 0x25, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0xc4, 0x14, 0x52, 0x00, 0xa4, 0xa0, 0x61, 0x4b, 0x40, 0x05, 0x14, 0x30, 0x12, 0x8a, 0x00, 0x5a, 0x4a, 0x04, 0x14, 0x50, 0x05, 0x8f, 0xad, 0x06, 0xb6, 0x2d, 0xad, 0x40, 0x71, 0x47, 0xa9, 0xeb, 0x43, 0x42, 0x17, 0xd8, 0x7d, 0xda, 0x4f, 0x6a, 0x7e, 0x62, 0x0a, 0x5a, 0x96, 0x86, 0x27, 0x7a, 0x28, 0xd0, 0x18, 0x1e, 0x68, 0xa2, 0xe2, 0x13, 0xbd, 0x2d, 0x20, 0x12, 0x8a, 0x00, 0x29, 0x29, 0x75, 0x00, 0xa2, 0x86, 0x01, 0x49, 0x47, 0x5b, 0x00, 0x51, 0x48, 0x41, 0x45, 0x1d, 0x40, 0x4a, 0x29, 0x0c, 0x5a, 0x4a, 0x04, 0x14, 0x51, 0x71, 0x85, 0x25, 0x02, 0x0a, 0x29, 0xd8, 0x02, 0x8a, 0x40, 0x14, 0x50, 0x31, 0x29, 0x69, 0xb1, 0x09, 0x46, 0x69, 0x31, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x21, 0x09, 0x4b, 0x40, 0x09, 0x45, 0x00, 0x14, 0xb4, 0x0c, 0x4a, 0x29, 0x88, 0x28, 0xa5, 0xb0, 0x05, 0x14, 0x0c, 0x28, 0xa6, 0x01, 0x45, 0x2b, 0x80, 0x51, 0x4c, 0x41, 0x45, 0x21, 0x89, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x58, 0x34, 0xa2, 0xb5, 0x1b, 0x0a, 0x3f, 0x4a, 0x02, 0xe1, 0xcf, 0xe7, 0x47, 0xe9, 0x54, 0x02, 0x52, 0xd0, 0x20, 0xa4, 0x34, 0x80, 0x29, 0x2a, 0x58, 0x0b, 0xde, 0x8a, 0x57, 0x10, 0x94, 0x50, 0x30, 0xa4, 0x34, 0x05, 0x82, 0x93, 0x9a, 0x5e, 0x4c, 0x02, 0x8a, 0x00, 0x28, 0xa6, 0x01, 0x49, 0x48, 0x42, 0x8a, 0x4a, 0x96, 0x01, 0x49, 0x54, 0x80, 0x29, 0x68, 0xb0, 0xd8, 0x94, 0x52, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x00, 0x51, 0x42, 0x60, 0x14, 0x50, 0x31, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x15, 0x5d, 0x00, 0x28, 0xa4, 0x21, 0x69, 0x29, 0x00, 0x51, 0x40, 0x05, 0x14, 0xc6, 0x14, 0x52, 0x00, 0xa2, 0x81, 0x05, 0x25, 0x03, 0x16, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x29, 0x28, 0x01, 0x69, 0x28, 0x00, 0xa2, 0x81, 0x0b, 0x49, 0x40, 0x05, 0x2d, 0x00, 0x4f, 0xf8, 0x51, 0xf4, 0xad, 0x99, 0x57, 0x0c, 0x51, 0x4d, 0x08, 0x38, 0x3c, 0x51, 0x8e, 0xdd, 0xe9, 0x8c, 0x06, 0x7b, 0xd1, 0x49, 0xb1, 0x01, 0xa3, 0xad, 0x21, 0x8b, 0x4d, 0xa9, 0x62, 0xd8, 0x4a, 0x3a, 0x52, 0xb0, 0xae, 0x2d, 0x14, 0x90, 0xc4, 0xef, 0x45, 0x50, 0x08, 0x69, 0x6a, 0x5f, 0x71, 0x58, 0x4a, 0x29, 0x8c, 0x28, 0xe9, 0x52, 0x01, 0x48, 0x6a, 0x84, 0x2d, 0x25, 0x20, 0x12, 0x8a, 0x06, 0x2d, 0x25, 0x2b, 0x88, 0x28, 0xa0, 0x61, 0x49, 0x4c, 0x42, 0xd1, 0x52, 0x02, 0x52, 0xd5, 0x0c, 0x4a, 0x29, 0x00, 0x51, 0x4d, 0x08, 0x28, 0xa4, 0x30, 0xa2, 0x98, 0x84, 0xa5, 0xa4, 0x80, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x84, 0x14, 0x50, 0xc6, 0x14, 0x50, 0x01, 0x45, 0x1a, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x60, 0x14, 0x52, 0xdc, 0x61, 0x45, 0x31, 0x09, 0x45, 0x20, 0x0a, 0x28, 0x18, 0xb4, 0x94, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x53, 0x02, 0xcf, 0x7a, 0x4a, 0xdd, 0xbb, 0xb1, 0x87, 0xf4, 0xa3, 0x9a, 0x5b, 0x08, 0x05, 0x14, 0x5f, 0x51, 0xd8, 0x28, 0x35, 0x37, 0xbb, 0x00, 0xfa, 0xd2, 0xd3, 0xb8, 0x34, 0x25, 0x15, 0x3a, 0x88, 0x29, 0x28, 0xd8, 0x42, 0x51, 0x48, 0x61, 0x45, 0x31, 0x05, 0x1c, 0x54, 0x83, 0x62, 0x51, 0x54, 0x30, 0xa2, 0xa0, 0x04, 0xa5, 0xa1, 0x80, 0x94, 0x50, 0x20, 0xa4, 0xa0, 0x61, 0x4b, 0x40, 0x09, 0xda, 0x8a, 0x62, 0x0a, 0x29, 0x00, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x29, 0x28, 0x60, 0x14, 0x52, 0x00, 0xa2, 0x98, 0x05, 0x25, 0x20, 0x16, 0x92, 0x98, 0x31, 0x69, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa4, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x00, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x96, 0x3f, 0x1a, 0x4a, 0xdb, 0xd0, 0xab, 0x75, 0x16, 0x8f, 0x4a, 0x44, 0x85, 0x2f, 0xb5, 0x3d, 0xc0, 0x69, 0xf4, 0xa7, 0x1e, 0x4d, 0x3b, 0x68, 0x02, 0x51, 0x52, 0x80, 0x28, 0xa0, 0x04, 0xa0, 0xd4, 0x85, 0x84, 0xa2, 0xa8, 0x02, 0x97, 0x23, 0xb5, 0x2b, 0x00, 0xda, 0x5a, 0x04, 0x25, 0x14, 0x98, 0xc2, 0x8a, 0x35, 0x10, 0x94, 0xb4, 0x98, 0x05, 0x21, 0xa0, 0x62, 0x52, 0xd2, 0x62, 0x10, 0xd1, 0x40, 0xc4, 0xa5, 0xaa, 0xd0, 0x41, 0x45, 0x2d, 0xc6, 0x25, 0x2d, 0x48, 0x84, 0xa2, 0x9e, 0xc3, 0x0a, 0x28, 0x00, 0xa2, 0x90, 0x05, 0x14, 0xc0, 0x29, 0x29, 0x00, 0xb4, 0x94, 0xc4, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x09, 0x45, 0x02, 0x16, 0x92, 0x81, 0x85, 0x14, 0x08, 0x29, 0x68, 0x01, 0x28, 0xa6, 0xc6, 0x14, 0x50, 0x01, 0x45, 0x20, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x2c, 0x52, 0x9c, 0x81, 0x9a, 0xde, 0xe9, 0xb1, 0xbd, 0xc6, 0xf1, 0x4b, 0x93, 0x48, 0x57, 0x0c, 0xd1, 0xc7, 0x5a, 0x9e, 0x5e, 0xa0, 0x00, 0xf3, 0xd2, 0x93, 0xa5, 0x30, 0x0a, 0x33, 0x4a, 0xf7, 0x00, 0xcd, 0x03, 0xa6, 0x68, 0x18, 0x52, 0xd3, 0x10, 0x9d, 0xe8, 0xa1, 0xea, 0x02, 0x52, 0xfe, 0x14, 0x81, 0x89, 0x49, 0x40, 0x58, 0x5e, 0xb4, 0x94, 0xac, 0x16, 0x0a, 0x29, 0x80, 0x0a, 0x28, 0x0b, 0x09, 0x45, 0x48, 0x05, 0x15, 0x40, 0x14, 0x54, 0x80, 0x52, 0x50, 0x80, 0x5a, 0x4a, 0x2c, 0x01, 0x45, 0x16, 0x01, 0x29, 0x69, 0xd8, 0x02, 0x92, 0x95, 0x80, 0x29, 0x69, 0x00, 0x52, 0x53, 0xb0, 0x05, 0x18, 0xa0, 0x02, 0x8a, 0x2c, 0x01, 0x45, 0x16, 0x00, 0xa4, 0xa5, 0x60, 0xb0, 0xb4, 0x94, 0xc0, 0x28, 0xa5, 0x60, 0x0a, 0x29, 0x00, 0x51, 0x54, 0x01, 0x45, 0x20, 0x0a, 0x29, 0xda, 0xe0, 0x14, 0x52, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x2c, 0x01, 0x45, 0x00, 0x25, 0x2d, 0x20, 0x12, 0x96, 0x98, 0x09, 0x4b, 0x40, 0x13, 0xf4, 0xa4, 0xad, 0x36, 0x41, 0xb8, 0x51, 0xdb, 0x14, 0xb9, 0x47, 0x61, 0x68, 0xa7, 0xb0, 0x05, 0x1d, 0x0d, 0x55, 0x84, 0x1d, 0x69, 0x2a, 0x7c, 0x80, 0x28, 0xa4, 0x30, 0xa2, 0x98, 0x82, 0x92, 0x8b, 0x80, 0x51, 0xef, 0x48, 0x04, 0xa2, 0xa4, 0x02, 0x8a, 0x3a, 0x05, 0xc2, 0x8a, 0x77, 0xb0, 0x05, 0x25, 0x20, 0xb8, 0xb4, 0x94, 0x00, 0x51, 0x48, 0x04, 0xa2, 0x98, 0x05, 0x14, 0x00, 0x66, 0x8a, 0x40, 0x14, 0x50, 0xc0, 0x29, 0x28, 0x00, 0xa0, 0x53, 0x00, 0xa2, 0x90, 0x82, 0x8a, 0x43, 0x0a, 0x28, 0x00, 0xa4, 0xa0, 0x05, 0xa4, 0xa6, 0x01, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa4, 0xa4, 0x30, 0xa5, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x4a, 0x29, 0x80, 0x52, 0xd0, 0x20, 0xa4, 0xa4, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x27, 0x3c, 0xd2, 0xd6, 0xb7, 0x18, 0x94, 0x67, 0xd6, 0x8d, 0xc0, 0x5a, 0x0f, 0x5a, 0x62, 0x0c, 0xd1, 0x4b, 0x50, 0xb0, 0x52, 0x54, 0xb0, 0x03, 0xd6, 0x92, 0x98, 0xc2, 0x96, 0x90, 0xae, 0x21, 0xa2, 0x9a, 0x00, 0xa2, 0x80, 0x12, 0x8a, 0x97, 0xa8, 0x05, 0x14, 0x58, 0x04, 0xa2, 0x9e, 0xe0, 0x14, 0x95, 0x20, 0x2d, 0x14, 0x00, 0x52, 0x52, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x77, 0x10, 0x52, 0x52, 0x18, 0x52, 0xd5, 0x00, 0x94, 0x50, 0x20, 0xa2, 0xa4, 0x41, 0x49, 0x40, 0xc5, 0xa2, 0x81, 0x85, 0x14, 0x08, 0x29, 0x29, 0x80, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x4a, 0x57, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x60, 0x25, 0x2d, 0x20, 0x0a, 0x29, 0x81, 0x39, 0xa2, 0xac, 0x76, 0x0e, 0xb4, 0x53, 0x18, 0xa2, 0x93, 0x9a, 0x68, 0x05, 0x1d, 0x28, 0xa0, 0x90, 0xa2, 0xa2, 0xe0, 0x25, 0x14, 0xc0, 0x29, 0x29, 0x05, 0x84, 0xa5, 0xaa, 0x00, 0xa3, 0x1e, 0xd5, 0x9f, 0x41, 0x09, 0xd6, 0x8a, 0x77, 0x18, 0x51, 0x4c, 0x04, 0xa5, 0xa5, 0x71, 0x09, 0x49, 0x4c, 0x05, 0xa2, 0x90, 0xc4, 0xa2, 0x95, 0xc4, 0x14, 0x51, 0xb8, 0x01, 0x34, 0x53, 0x00, 0xa2, 0x90, 0x09, 0x45, 0x03, 0x0a, 0x29, 0x08, 0x4a, 0x5a, 0x60, 0x14, 0x66, 0x90, 0x58, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x60, 0x25, 0x2d, 0x20, 0x12, 0x96, 0x80, 0x12, 0x96, 0x81, 0x89, 0x45, 0x31, 0x05, 0x14, 0x80, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4e, 0x7a, 0x51, 0xda, 0xb7, 0x28, 0x3e, 0x94, 0x71, 0xef, 0x4c, 0x41, 0x4e, 0xa9, 0x01, 0xb4, 0xb4, 0xc4, 0x27, 0xe1, 0x45, 0x26, 0x3b, 0x85, 0x1d, 0xe9, 0x08, 0x28, 0xa9, 0xea, 0x02, 0x52, 0x73, 0x43, 0x01, 0x71, 0x4a, 0x38, 0x6a, 0x42, 0x1b, 0xd2, 0x8a, 0x10, 0xc4, 0x34, 0xb4, 0x58, 0x04, 0xa2, 0x98, 0x82, 0x92, 0x86, 0xc6, 0x2d, 0x25, 0x48, 0x82, 0x8a, 0x12, 0x18, 0x51, 0x4c, 0x41, 0x45, 0x48, 0x09, 0x45, 0x31, 0x85, 0x14, 0x08, 0x28, 0xa4, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x10, 0x94, 0x50, 0x01, 0x40, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x29, 0x8c, 0x29, 0x29, 0x00, 0x51, 0x4c, 0x02, 0x8a, 0x40, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0xb4, 0x08, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x09, 0x4b, 0x40, 0x13, 0xe6, 0x96, 0xb4, 0xb8, 0x75, 0x13, 0x22, 0x8e, 0xf5, 0x6b, 0x51, 0x8b, 0xc7, 0x6a, 0x4a, 0xa6, 0x01, 0x4b, 0x51, 0xcc, 0x02, 0x51, 0x9a, 0x62, 0xb0, 0x94, 0xb5, 0x37, 0x00, 0xa4, 0xa4, 0x01, 0x45, 0x27, 0xdc, 0x04, 0xa5, 0xa6, 0x02, 0x52, 0xd2, 0x01, 0x28, 0xa4, 0x02, 0x51, 0x40, 0x05, 0x14, 0x9e, 0xa0, 0x14, 0x94, 0x02, 0x0a, 0x28, 0x60, 0x25, 0x2d, 0x3d, 0x01, 0x89, 0x45, 0x21, 0x20, 0xa2, 0x81, 0x85, 0x14, 0x80, 0x28, 0xa0, 0x41, 0x45, 0x30, 0x0a, 0x29, 0x00, 0x94, 0x53, 0x00, 0xa2, 0x8b, 0x8c, 0x28, 0xa6, 0x20, 0xa4, 0xa9, 0x18, 0x52, 0xd3, 0xb0, 0x82, 0x92, 0x90, 0x05, 0x2d, 0x03, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x2c, 0x02, 0x51, 0x40, 0x85, 0xa2, 0x81, 0x89, 0x45, 0x00, 0x2d, 0x14, 0xc0, 0x9f, 0x14, 0xbd, 0xaa, 0x86, 0x1c, 0xfe, 0x14, 0x55, 0xa6, 0x98, 0x84, 0xa2, 0xa8, 0x62, 0x8e, 0x3a, 0x52, 0x54, 0xdd, 0x08, 0x28, 0xa0, 0x04, 0xa5, 0xa0, 0x04, 0x34, 0xb5, 0x20, 0x25, 0x15, 0x37, 0x01, 0x29, 0x4d, 0x30, 0x1b, 0x47, 0xb5, 0x48, 0x0b, 0x49, 0x4f, 0xa0, 0x07, 0x7a, 0x28, 0x40, 0x14, 0x53, 0x0b, 0x85, 0x15, 0x20, 0x25, 0x14, 0xc4, 0x14, 0x50, 0x30, 0xa4, 0xa0, 0x41, 0x4b, 0x53, 0x61, 0x89, 0x45, 0x00, 0x14, 0x50, 0x21, 0x29, 0x69, 0x80, 0x94, 0x50, 0x02, 0xd2, 0x52, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x00, 0x28, 0xa6, 0x30, 0xa4, 0xa4, 0x01, 0x4b, 0x40, 0x09, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x98, 0xc2, 0x8a, 0x42, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x28, 0xa0, 0x62, 0x52, 0xd0, 0x05, 0x8f, 0xf3, 0xd2, 0x93, 0xad, 0x6a, 0xc0, 0x29, 0x6a, 0x96, 0xa5, 0x07, 0x6a, 0x3b, 0x54, 0x8a, 0xc0, 0x28, 0xa3, 0x46, 0x21, 0x29, 0x6a, 0xb6, 0x0b, 0x09, 0x49, 0x51, 0x70, 0x0a, 0x0d, 0x34, 0x01, 0xda, 0x92, 0x96, 0x80, 0x14, 0xb5, 0x3d, 0x44, 0x25, 0x14, 0xf4, 0x18, 0x94, 0x52, 0x00, 0xa2, 0x86, 0xc0, 0x29, 0x28, 0xb0, 0x82, 0x8a, 0x2c, 0x01, 0x45, 0x0c, 0x02, 0x92, 0x80, 0x16, 0x8a, 0x90, 0x12, 0x8a, 0x01, 0x85, 0x14, 0xc0, 0x28, 0xa0, 0x04, 0xa2, 0x90, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x4a, 0x5a, 0x00, 0x4a, 0x28, 0x01, 0x69, 0x28, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x92, 0x81, 0x0b, 0x45, 0x03, 0x0a, 0x4a, 0x00, 0x5a, 0x4a, 0x00, 0xb1, 0xf8, 0x52, 0x56, 0xdb, 0x0c, 0x5c, 0x8e, 0x98, 0xa5, 0xa4, 0x02, 0x52, 0xd1, 0x21, 0x05, 0x14, 0xc6, 0x25, 0x14, 0x08, 0x05, 0x15, 0x3d, 0x00, 0x4a, 0x2a, 0x77, 0x00, 0xe6, 0x93, 0xbd, 0x08, 0x05, 0xa6, 0xd5, 0x74, 0x04, 0x2d, 0x21, 0xa3, 0x70, 0x0a, 0x2a, 0x40, 0x28, 0xa6, 0x20, 0xa2, 0xa6, 0xe0, 0x14, 0x94, 0x20, 0x0a, 0x29, 0xb0, 0x0a, 0x4a, 0x40, 0x2d, 0x25, 0x00, 0x14, 0x52, 0x18, 0x94, 0xb4, 0xc4, 0x14, 0x50, 0x31, 0x29, 0x69, 0x00, 0x94, 0x50, 0x80, 0x28, 0xa0, 0x02, 0x8a, 0x60, 0x14, 0x52, 0x10, 0x51, 0x40, 0x09, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x04, 0x14, 0x53, 0x18, 0x51, 0x40, 0x05, 0x14, 0x84, 0x14, 0x50, 0x30, 0xa4, 0xa6, 0x01, 0x45, 0x20, 0x16, 0x8a, 0x00, 0x29, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x96, 0x80, 0x27, 0xed, 0x49, 0xfc, 0xeb, 0x6e, 0x50, 0x1d, 0x8a, 0x2a, 0x47, 0x71, 0x28, 0xa7, 0xa0, 0xc0, 0xd1, 0x54, 0x20, 0xa2, 0x90, 0x82, 0x8a, 0x86, 0x80, 0x4c, 0xd1, 0x4e, 0xc8, 0x41, 0x45, 0x21, 0x89, 0x45, 0x00, 0x14, 0x52, 0x01, 0x28, 0xa0, 0x41, 0x45, 0x00, 0x14, 0x94, 0x0d, 0x05, 0x14, 0xac, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa4, 0xa4, 0x01, 0x45, 0x30, 0x0a, 0x28, 0x00, 0xa4, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x90, 0xc2, 0x8a, 0x62, 0x0a, 0x4a, 0x40, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x31, 0x69, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x92, 0x80, 0x16, 0x8a, 0x04, 0x25, 0x14, 0x00, 0x51, 0x40, 0x0b, 0x49, 0x40, 0xc5, 0xa4, 0xa0, 0x09, 0xf3, 0x45, 0x6c, 0x31, 0x7b, 0x52, 0xd4, 0xe8, 0x21, 0x28, 0xe9, 0xd6, 0x98, 0xc2, 0x96, 0x9d, 0xc4, 0x26, 0x68, 0xa4, 0x08, 0x4a, 0x5e, 0xd4, 0xae, 0x02, 0x51, 0x4d, 0x87, 0x50, 0xa4, 0xa4, 0x01, 0x49, 0x4b, 0xa8, 0x85, 0xa4, 0xa4, 0x3b, 0x85, 0x14, 0x20, 0x0a, 0x4a, 0x4c, 0x05, 0xa4, 0xa0, 0x41, 0x4b, 0x40, 0xc4, 0xa4, 0xa7, 0xd0, 0x02, 0x8a, 0x04, 0x2d, 0x25, 0x20, 0x0a, 0x29, 0x00, 0x51, 0x4c, 0x62, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x42, 0x51, 0x4c, 0x62, 0xd2, 0x52, 0x10, 0xb4, 0x94, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x12, 0x96, 0x80, 0x0a, 0x28, 0x10, 0x94, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x16, 0x92, 0x80, 0x16, 0x92, 0x81, 0x05, 0x14, 0x01, 0x63, 0x14, 0x56, 0xf7, 0x28, 0x28, 0xa8, 0x96, 0xa2, 0x61, 0xdf, 0xa5, 0x2f, 0xd0, 0x53, 0xb0, 0xc4, 0x3d, 0x28, 0xe2, 0x9f, 0x40, 0x0a, 0x2a, 0x44, 0x25, 0x2d, 0x30, 0x12, 0x8a, 0x4c, 0x03, 0x34, 0x94, 0x96, 0xc0, 0x2e, 0x68, 0xa9, 0x01, 0x29, 0x2a, 0xd0, 0x05, 0x14, 0x80, 0x28, 0xa4, 0x02, 0x52, 0xd2, 0x01, 0x29, 0x69, 0x80, 0x94, 0x52, 0x10, 0x94, 0xb4, 0x0c, 0x4a, 0x28, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x42, 0x52, 0xd2, 0x01, 0x28, 0xa0, 0x61, 0x45, 0x1d, 0x44, 0x14, 0x53, 0xb8, 0xc2, 0x92, 0x90, 0x82, 0x8a, 0x2e, 0x31, 0x68, 0xa0, 0x42, 0x51, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x10, 0x52, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x0b, 0x49, 0x40, 0xc5, 0xa4, 0xa0, 0x0b, 0x14, 0x66, 0xb5, 0x2b, 0x40, 0xa2, 0x90, 0x82, 0x8a, 0x16, 0xe2, 0xe8, 0x1d, 0x28, 0xa7, 0xb8, 0x21, 0x29, 0x73, 0x47, 0x40, 0x0a, 0x4a, 0x40, 0x14, 0x76, 0xa0, 0x62, 0x0a, 0x5a, 0x91, 0x09, 0x45, 0x08, 0x02, 0x83, 0x40, 0x09, 0x45, 0x31, 0x05, 0x15, 0x37, 0x01, 0x28, 0xa0, 0x05, 0xa4, 0xa2, 0xe0, 0x14, 0x53, 0x18, 0x52, 0x52, 0x00, 0xa2, 0x90, 0x05, 0x15, 0x42, 0x0a, 0x4a, 0x00, 0x29, 0x69, 0x00, 0x94, 0x50, 0x01, 0x45, 0x21, 0x89, 0x4b, 0x40, 0x82, 0x8a, 0x00, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x06, 0x2d, 0x25, 0x02, 0x0a, 0x4a, 0x06, 0x2d, 0x14, 0x00, 0x94, 0xb4, 0x00, 0x51, 0x40, 0x09, 0x4b, 0x40, 0x05, 0x14, 0x08, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x96, 0x81, 0x89, 0x45, 0x02, 0x16, 0x92, 0x84, 0x32, 0xc6, 0x73, 0x47, 0xe1, 0x5a, 0xdc, 0x04, 0xfd, 0x68, 0xa2, 0xe3, 0x16, 0x96, 0x95, 0xf5, 0x00, 0xa4, 0xaa, 0x10, 0x66, 0x8a, 0x40, 0x14, 0x52, 0x01, 0x28, 0xa4, 0x02, 0x52, 0xd0, 0x02, 0x1a, 0x0d, 0x20, 0x12, 0x96, 0x9b, 0x01, 0x28, 0xa4, 0x01, 0x45, 0x02, 0x12, 0x96, 0x90, 0xc2, 0x92, 0x90, 0x82, 0x8a, 0x60, 0x14, 0x94, 0x74, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x48, 0x04, 0xa5, 0xa0, 0x42, 0x51, 0x4c, 0x62, 0xd2, 0x52, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x00, 0x51, 0x4c, 0x62, 0x51, 0x48, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x42, 0x12, 0x8a, 0x63, 0x0a, 0x5a, 0x00, 0x4a, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0xc0, 0x28, 0xa4, 0x01, 0x45, 0x03, 0x2c, 0x1a, 0x4a, 0xd7, 0xa0, 0x0b, 0x45, 0x30, 0x13, 0x3e, 0xd4, 0x53, 0xb0, 0x05, 0x2d, 0x20, 0xb8, 0x94, 0x53, 0xbe, 0x80, 0x14, 0x54, 0xd8, 0x02, 0x92, 0x97, 0x40, 0x0a, 0x5a, 0x40, 0x25, 0x19, 0xa0, 0x04, 0xa5, 0xa5, 0x60, 0x13, 0x14, 0x1a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x20, 0x12, 0x8a, 0x63, 0x0a, 0x28, 0x62, 0x12, 0x8a, 0x06, 0x14, 0x52, 0x10, 0x51, 0x4c, 0x04, 0xa5, 0xa9, 0x60, 0x25, 0x2d, 0x03, 0x12, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x92, 0x84, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x51, 0x40, 0x84, 0xa2, 0x80, 0x16, 0x8a, 0x00, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x96, 0x81, 0x85, 0x25, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x04, + 0xff, 0x00, 0x5a, 0x2b, 0x50, 0x16, 0x92, 0x81, 0x85, 0x2d, 0x50, 0x07, 0xe1, 0x49, 0x48, 0x48, 0x5f, 0xc2, 0x8a, 0x4c, 0x04, 0xa2, 0x90, 0x20, 0xa4, 0xa5, 0x6b, 0x00, 0xb4, 0x50, 0x02, 0x52, 0x51, 0x70, 0x0a, 0x29, 0x00, 0x51, 0x45, 0x80, 0x28, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x14, 0x00, 0x94, 0xb4, 0x80, 0x29, 0x29, 0x88, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x12, 0x96, 0x90, 0xc4, 0xa2, 0x9d, 0xc4, 0x14, 0x53, 0x00, 0xa2, 0xa4, 0x61, 0x49, 0x40, 0x05, 0x2d, 0x30, 0x0a, 0x4a, 0x04, 0x14, 0x52, 0x00, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x52, 0x50, 0x21, 0x68, 0xa0, 0x02, 0x8a, 0x00, 0x29, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x22, 0xc5, 0x27, 0x7a, 0xd0, 0x6c, 0x28, 0xaa, 0x00, 0x3d, 0xa8, 0xa0, 0x05, 0xa2, 0x8e, 0x83, 0x0a, 0x4a, 0x95, 0xb8, 0x82, 0x8a, 0x00, 0x4a, 0x5a, 0x64, 0x85, 0x25, 0x49, 0x41, 0x45, 0x26, 0x02, 0x51, 0x4c, 0x02, 0x92, 0x80, 0x16, 0x8a, 0x90, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x00, 0x69, 0x28, 0x43, 0x0a, 0x29, 0x88, 0x5a, 0x4a, 0x43, 0x0a, 0x28, 0xb0, 0x05, 0x25, 0x00, 0x14, 0x52, 0x10, 0xb4, 0x94, 0x0c, 0x28, 0xa0, 0x41, 0x49, 0x40, 0xc5, 0xa2, 0x80, 0x12, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x28, 0xa0, 0x04, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x9f, 0x14, 0x56, 0xc3, 0x0a, 0x5e, 0x94, 0x5c, 0x42, 0x52, 0xf5, 0xa2, 0xe0, 0x27, 0x7a, 0x5a, 0x43, 0x13, 0x34, 0xb4, 0x6c, 0x21, 0x29, 0x29, 0x6e, 0x02, 0xd1, 0x48, 0x2e, 0x25, 0x25, 0x30, 0x16, 0x92, 0x90, 0x0b, 0x49, 0x49, 0x80, 0x51, 0x49, 0x00, 0x94, 0x55, 0x00, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x29, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x49, 0x40, 0x05, 0x14, 0x00, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x4a, 0x28, 0x00, 0xa5, 0xa0, 0x42, 0x51, 0x40, 0x05, 0x14, 0xc6, 0x14, 0x52, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x29, 0x29, 0x88, 0x29, 0x69, 0x0c, 0x28, 0xa0, 0x42, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x9e, 0x8e, 0x2b, 0x60, 0x0a, 0x5a, 0x00, 0x28, 0x14, 0x00, 0x94, 0xb4, 0x0c, 0x4a, 0x29, 0x07, 0x40, 0xa2, 0xa4, 0x42, 0x1a, 0x3e, 0x94, 0xc0, 0x28, 0xa9, 0xd8, 0x04, 0xa5, 0xa6, 0x02, 0x51, 0xd6, 0x96, 0xe0, 0x14, 0x52, 0xb0, 0x05, 0x25, 0x30, 0x0a, 0x28, 0xb0, 0x0b, 0x49, 0x48, 0x02, 0x92, 0x8e, 0x80, 0x14, 0x52, 0x10, 0x51, 0x4c, 0x02, 0x8a, 0x40, 0x25, 0x2d, 0x03, 0x12, 0x8a, 0x60, 0x14, 0x50, 0x01, 0x45, 0x20, 0x0a, 0x28, 0x01, 0x29, 0x68, 0x10, 0x94, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0x40, 0x84, 0xa5, 0xa4, 0x30, 0xa2, 0x80, 0x12, 0x8a, 0x00, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x02, 0xc5, 0x15, 0xb3, 0x18, 0x52, 0x52, 0x10, 0xb4, 0x53, 0x60, 0x14, 0x94, 0x0c, 0x3b, 0x51, 0x4a, 0xe2, 0x0a, 0x29, 0x00, 0x94, 0x51, 0x6b, 0x80, 0x51, 0x48, 0x02, 0x8a, 0x40, 0x25, 0x14, 0xd8, 0x05, 0x15, 0x20, 0x25, 0x14, 0xc0, 0x28, 0xa0, 0x02, 0x8a, 0x9b, 0x08, 0x4a, 0x2a, 0x80, 0x28, 0xa9, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x01, 0x29, 0x68, 0x01, 0x28, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x28, 0x10, 0x94, 0x52, 0x18, 0xb4, 0x94, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x02, 0x12, 0x8a, 0x06, 0x14, 0xb4, 0x00, 0x94, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x93, 0xd1, 0x5a, 0xbe, 0xc8, 0x1e, 0xa1, 0x4b, 0xde, 0x82, 0x83, 0x34, 0x11, 0x48, 0x91, 0x05, 0x1d, 0xe9, 0xb1, 0x86, 0x69, 0x29, 0xd8, 0x42, 0xd1, 0x51, 0x24, 0x02, 0x51, 0x54, 0x01, 0x45, 0x4d, 0xc0, 0x29, 0x29, 0x00, 0x51, 0x45, 0xc0, 0x4e, 0xf4, 0x52, 0x00, 0xa2, 0xa8, 0x02, 0x8a, 0x80, 0x12, 0x8a, 0xa0, 0x0a, 0x28, 0x00, 0xa2, 0x90, 0x05, 0x14, 0x82, 0xe1, 0x45, 0x08, 0x04, 0xa2, 0x98, 0x05, 0x14, 0x84, 0x14, 0x50, 0x30, 0xa4, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0xb4, 0x0c, 0x4a, 0x5a, 0x04, 0x25, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0xc4, 0xa5, 0xa0, 0x42, 0x52, 0xd0, 0x31, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x09, 0xfa, 0xd2, 0xf7, 0xad, 0x87, 0x70, 0xdb, 0xf9, 0x52, 0x51, 0xab, 0x00, 0xa5, 0xa6, 0x3b, 0x09, 0x45, 0x40, 0x98, 0x51, 0xf5, 0xa6, 0x02, 0x51, 0x48, 0x42, 0xf5, 0xa2, 0x92, 0x01, 0x28, 0xa3, 0xa0, 0x82, 0x92, 0x90, 0xc2, 0x83, 0x43, 0x42, 0x0a, 0x4a, 0x43, 0x0a, 0x4a, 0x60, 0x14, 0xb4, 0x08, 0x29, 0x2a, 0x6e, 0x01, 0x45, 0x0c, 0x61, 0x45, 0x31, 0x05, 0x14, 0x80, 0x29, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0x48, 0x02, 0x92, 0x86, 0x01, 0x45, 0x17, 0x18, 0x52, 0xd0, 0x02, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x93, 0xe2, 0x8a, 0xd6, 0x21, 0x71, 0x28, 0xaa, 0x60, 0x85, 0xcd, 0x15, 0x2c, 0x62, 0xd2, 0x66, 0x81, 0x58, 0x28, 0xa0, 0x02, 0x92, 0x90, 0x05, 0x14, 0x00, 0x52, 0x50, 0x01, 0x45, 0x20, 0x0a, 0x29, 0x00, 0x94, 0x55, 0x00, 0x51, 0x52, 0x01, 0x45, 0x00, 0x25, 0x2d, 0x48, 0x09, 0x45, 0x00, 0x14, 0x53, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x40, 0x14, 0x53, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x40, 0x14, 0x53, 0x00, 0xa2, 0x90, 0x05, 0x14, 0xc0, 0x28, 0xa4, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x0c, 0x41, 0x49, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x27, 0xa3, 0x81, 0x5a, 0xa6, 0x02, 0x52, 0xd2, 0xb8, 0x0b, 0x45, 0x58, 0xc6, 0x9a, 0x5a, 0x42, 0x0a, 0x2a, 0x40, 0x29, 0x28, 0x00, 0xa2, 0x8d, 0x80, 0x28, 0xa4, 0x02, 0x51, 0x40, 0x05, 0x14, 0x84, 0x25, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x3a, 0x80, 0x51, 0x52, 0x02, 0x51, 0x4c, 0x02, 0x8a, 0x04, 0x14, 0x52, 0x01, 0x28, 0xa6, 0x30, 0xa2, 0x81, 0x0b, 0x49, 0x48, 0x62, 0x52, 0xd0, 0x20, 0xa2, 0x80, 0x12, 0x96, 0x81, 0x89, 0x45, 0x17, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x52, 0x50, 0x31, 0x69, 0x28, 0x00, 0xa5, 0xa0, 0x04, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x02, 0x6a, 0x5e, 0xd5, 0xa8, 0xd8, 0x94, 0xb4, 0xd8, 0x82, 0x8f, 0xad, 0x03, 0x0a, 0x2a, 0x6e, 0x21, 0x29, 0x68, 0x01, 0x28, 0xa1, 0x80, 0xb4, 0xda, 0x40, 0x2d, 0x25, 0x00, 0x14, 0x52, 0x00, 0xc5, 0x14, 0x00, 0x94, 0x55, 0x00, 0x51, 0x52, 0x17, 0x0a, 0x28, 0x60, 0x25, 0x14, 0x80, 0x29, 0x69, 0x88, 0x4a, 0x29, 0x0c, 0x28, 0xa4, 0x21, 0x29, 0x69, 0x8c, 0x4a, 0x28, 0x00, 0xa2, 0x90, 0x84, 0xa5, 0xa6, 0x01, 0x45, 0x20, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x98, 0x05, 0x14, 0x86, 0x25, 0x2d, 0x00, 0x14, 0x94, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x04, 0xf4, 0x13, 0xcd, 0x5e, 0xec, 0x61, 0xde, 0x8a, 0xad, 0x04, 0xc5, 0xa2, 0x9a, 0x01, 0x28, 0xe6, 0x98, 0x05, 0x15, 0x20, 0x26, 0x28, 0xa4, 0x01, 0x45, 0x4e, 0x80, 0x14, 0x94, 0xc0, 0x28, 0xa0, 0x41, 0x49, 0x4a, 0xc3, 0x16, 0x92, 0x90, 0x05, 0x14, 0x72, 0x80, 0x51, 0x40, 0x84, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x52, 0x52, 0x18, 0xb4, 0x1a, 0x42, 0x12, 0x96, 0x81, 0x89, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x4a, 0x00, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x52, 0x50, 0x02, 0xd1, 0x40, 0x82, 0x92, 0x81, 0x8b, 0x49, 0x40, 0x82, 0x8a, 0x00, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x58, 0xa4, 0xed, 0x5a, 0x80, 0xbd, 0xe9, 0x29, 0xa0, 0x61, 0x45, 0x26, 0x09, 0x05, 0x1d, 0x29, 0x80, 0x51, 0x52, 0x02, 0x51, 0x40, 0x05, 0x25, 0x00, 0x2e, 0x68, 0xa4, 0x21, 0x29, 0x69, 0x0c, 0x4a, 0x4a, 0x2e, 0x80, 0x5a, 0x29, 0x08, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x09, 0x45, 0x30, 0x0a, 0x29, 0x00, 0x51, 0x40, 0x82, 0x92, 0x90, 0xc2, 0x96, 0x98, 0x84, 0xa2, 0x86, 0x01, 0x45, 0x03, 0x0a, 0x29, 0x00, 0x94, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x85, 0x25, 0x00, 0x14, 0xb4, 0x00, 0x94, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x01, 0x35, 0x2d, 0x6b, 0xb8, 0x30, 0xa2, 0x9a, 0xd0, 0x02, 0x8a, 0x40, 0x1d, 0xe8, 0xa0, 0x02, 0x8a, 0x24, 0xae, 0x01, 0x49, 0x40, 0x05, 0x14, 0x98, 0x05, 0x21, 0xa3, 0x60, 0x0a, 0x2a, 0x1b, 0xd4, 0x41, 0x49, 0x48, 0x05, 0xa4, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x28, 0x10, 0x94, 0x50, 0x30, 0xa2, 0x93, 0x10, 0x51, 0x40, 0xc2, 0x92, 0x81, 0x05, 0x14, 0xc0, 0x28, 0xa0, 0x02, 0x8a, 0x4c, 0x61, 0x45, 0x00, 0x14, 0x94, 0xc0, 0x28, 0xa0, 0x02, 0x8a, 0x42, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x25, 0x00, 0x2d, 0x25, 0x02, 0x0a, 0x5a, 0x06, 0x14, 0x94, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x22, 0x7a, 0x53, 0x5a, 0x49, 0x8c, 0x4a, 0x28, 0x40, 0x14, 0x55, 0x0c, 0x4a, 0x5a, 0x04, 0xc4, 0xa5, 0xa9, 0xe6, 0x18, 0x51, 0x52, 0x98, 0x84, 0xa2, 0x98, 0x05, 0x25, 0x20, 0x0e, 0xd4, 0x50, 0x84, 0x25, 0x2d, 0x00, 0x25, 0x14, 0x0c, 0x28, 0xa4, 0x20, 0xa4, 0xaa, 0x18, 0x51, 0x52, 0xc4, 0x14, 0x52, 0x00, 0xa4, 0xa6, 0x31, 0x69, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x63, 0x0a, 0x28, 0x10, 0x94, 0xb4, 0x0c, 0x4a, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x49, 0x40, 0x0b, 0x49, 0x40, 0x0b, 0x49, 0x40, 0x85, 0xa2, 0x81, 0x89, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4c, 0x69, 0xdf, 0x85, 0x69, 0x60, 0xe8, 0x37, 0xa7, 0x4a, 0x3a, 0x55, 0x00, 0xb4, 0x51, 0x60, 0x0a, 0x2a, 0x6c, 0x01, 0x9a, 0x4a, 0x56, 0xb3, 0x00, 0xa3, 0xa5, 0x30, 0x0a, 0x29, 0x08, 0x29, 0x28, 0x00, 0xa2, 0x90, 0x05, 0x14, 0x86, 0x14, 0x94, 0xc0, 0x28, 0xa4, 0x02, 0x52, 0xd0, 0x02, 0x51, 0x4c, 0x42, 0x52, 0xd2, 0x00, 0xa2, 0x93, 0x04, 0x14, 0x94, 0xc6, 0x2d, 0x25, 0x21, 0x05, 0x14, 0x0c, 0x4a, 0x5a, 0x04, 0x25, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x00, 0x14, 0x50, 0x01, 0x49, 0x40, 0xc2, 0x8a, 0x00, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x27, 0xa2, 0xb5, 0x18, 0x94, 0xb4, 0x06, 0xe1, 0x4b, 0xda, 0x90, 0x31, 0x29, 0x7b, 0xd0, 0x21, 0x28, 0xa1, 0x80, 0x94, 0x52, 0xb0, 0x05, 0x14, 0xc0, 0x33, 0x49, 0x4b, 0xd0, 0x2c, 0x14, 0x52, 0x12, 0x0a, 0x4a, 0x06, 0x14, 0x52, 0x60, 0x14, 0x52, 0xb0, 0x05, 0x25, 0x16, 0x00, 0xa2, 0x98, 0x82, 0x8a, 0x40, 0x14, 0x50, 0x01, 0x49, 0x40, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x03, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x12, 0x8a, 0x04, 0x2d, 0x25, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x27, 0xa0, 0x55, 0x94, 0x06, 0x92, 0xa8, 0x42, 0xd1, 0x9a, 0x34, 0x00, 0xa2, 0x86, 0x84, 0x25, 0x2d, 0x17, 0x01, 0x28, 0xa4, 0x01, 0x49, 0x46, 0xc0, 0x14, 0x52, 0x00, 0xa2, 0x90, 0x09, 0x45, 0x48, 0x05, 0x15, 0x40, 0x14, 0x52, 0x00, 0xa4, 0xa3, 0x98, 0x41, 0x45, 0x3b, 0x80, 0x51, 0x9a, 0x40, 0x14, 0x52, 0x18, 0x94, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x4c, 0x04, 0xa5, 0xa0, 0x02, 0x92, 0x90, 0x82, 0x8a, 0x00, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x52, 0x50, 0x20, 0xa5, 0xa0, 0x61, 0x49, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4d, 0x4b, 0x5a, 0x80, 0x51, 0x46, 0xc0, 0x25, 0x2d, 0x49, 0x48, 0x28, 0xa6, 0x26, 0x25, 0x2d, 0x21, 0x09, 0x45, 0x3b, 0x80, 0x51, 0x50, 0xc0, 0x4a, 0x28, 0x00, 0xa2, 0x98, 0x09, 0x45, 0x3e, 0x82, 0x0a, 0x2a, 0x6c, 0x30, 0xa2, 0x98, 0x09, 0x45, 0x48, 0x82, 0x8a, 0x63, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x5d, 0x40, 0x28, 0xa6, 0x01, 0x49, 0x48, 0x05, 0xa4, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x12, 0x96, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x01, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x9f, 0x9a, 0x2b, 0x5b, 0x8f, 0x70, 0xa2, 0x8b, 0x00, 0x52, 0x50, 0x90, 0x82, 0x96, 0x95, 0x80, 0x43, 0xcd, 0x2d, 0x00, 0x25, 0x14, 0x80, 0x28, 0xa0, 0x04, 0xa2, 0x81, 0x05, 0x14, 0x86, 0x14, 0x50, 0x02, 0x51, 0x4c, 0x02, 0x8a, 0x86, 0x01, 0x49, 0x46, 0xc2, 0x0a, 0x29, 0x8c, 0x28, 0xa0, 0x02, 0x92, 0x98, 0x82, 0x8a, 0x06, 0x14, 0x54, 0x88, 0x28, 0xa6, 0x30, 0xa4, 0xa4, 0x21, 0x68, 0xa0, 0x62, 0x51, 0x40, 0x85, 0xa4, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x21, 0x29, 0x68, 0x18, 0x51, 0x40, 0x05, 0x14, 0x08, 0x29, 0x28, 0x18, 0xb4, 0x94, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4c, 0x7d, 0xe9, 0x7d, 0xaa, 0xef, 0xd8, 0x02, 0x8a, 0xae, 0x80, 0x14, 0xb4, 0x7a, 0x00, 0x9d, 0xa9, 0x0d, 0x2b, 0x80, 0xb4, 0x50, 0x02, 0x51, 0xd2, 0x90, 0x05, 0x14, 0x80, 0x29, 0x2a, 0x80, 0x31, 0x45, 0x20, 0x0a, 0x29, 0x00, 0x94, 0x52, 0x60, 0x25, 0x28, 0xa4, 0x02, 0x52, 0x55, 0x5c, 0x05, 0xa2, 0x90, 0x05, 0x14, 0xc0, 0x28, 0xa4, 0x01, 0x49, 0x40, 0x05, 0x14, 0x84, 0x14, 0x50, 0x01, 0x45, 0x17, 0x18, 0x52, 0x50, 0x20, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x82, 0x92, 0x81, 0x85, 0x2d, 0x02, 0x12, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x7f, + // EOI + 0xff, 0xd9}; +// 21:15:35.200 > unexpected jpeg typecode 0xd8 +// 21:15:35.203 > unexpected jpeg typecode 0xd8 +// 21:15:35.205 > [ 49411][I][CStreamer.cpp:197] streamFrame(): Data: Len=6972 +static unsigned char jpeg_data[7845] = { + 0xe0, 0xc7, 0xd6, 0x91, 0xb8, 0xae, 0x9d, 0x6e, 0x02, 0xf3, 0xcf, 0x14, 0x87, 0x93, 0x48, 0x61, 0xec, 0x29, 0x7a, 0x8a, 0x77, 0x01, 0x07, 0xbd, 0x2d, 0x16, 0xd0, 0x42, 0x67, 0x8a, 0x52, 0x3d, 0x29, 0x0c, 0x4c, 0xd0, 0x28, 0x10, 0x94, 0x67, 0x9a, 0x90, 0x0f, 0xa9, 0xa2, 0xa1, 0x80, 0x1c, 0xf6, 0xa4, 0xe6, 0x95, 0xd8, 0x07, 0x22, 0x8a, 0xa1, 0x05, 0x25, 0x3b, 0x08, 0x3a, 0xd1, 0xc5, 0x46, 0xa5, 0x05, 0x1e, 0xf4, 0x05, 0x83, 0xeb, 0x45, 0x20, 0x0a, 0x29, 0x80, 0x94, 0x53, 0xb9, 0x23, 0x7b, 0xd3, 0xa9, 0x5c, 0x62, 0x52, 0xd2, 0xb7, 0x50, 0x13, 0xb5, 0x2f, 0xd2, 0x8b, 0x0c, 0x4a, 0x2a, 0xc0, 0x28, 0xa8, 0x01, 0x0d, 0x2d, 0x02, 0xb0, 0x1a, 0x28, 0x00, 0xa4, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xcd, 0x3b, 0x00, 0x51, 0x48, 0x02, 0x92, 0x80, 0x0a, 0x29, 0x8d, 0x8b, 0x45, 0x21, 0x05, 0x25, 0x26, 0xc4, 0x14, 0x53, 0x1a, 0x0a, 0x28, 0x01, 0x29, 0x69, 0x30, 0x0a, 0x29, 0x8c, 0x28, 0xa6, 0x20, 0xa2, 0x95, 0xc0, 0x28, 0xa0, 0x61, 0x49, 0x48, 0x41, 0x4b, 0x55, 0x6d, 0x40, 0x9e, 0x90, 0x74, 0xfb, 0xbc, 0xd6, 0xbe, 0x85, 0xb6, 0x3b, 0xb5, 0x25, 0x4f, 0x28, 0x85, 0xe3, 0xbd, 0x27, 0x5a, 0xab, 0x00, 0xb4, 0x7d, 0x4d, 0x24, 0x21, 0xb9, 0x3c, 0x53, 0xb3, 0xf9, 0xd3, 0xea, 0x02, 0x0a, 0x3d, 0xe8, 0xf3, 0x00, 0xa3, 0x1c, 0x73, 0x4a, 0xe0, 0x27, 0x4e, 0x94, 0x95, 0x31, 0xdc, 0x10, 0xb4, 0x74, 0xa0, 0x5d, 0x42, 0x93, 0xbd, 0x00, 0x03, 0xbd, 0x1d, 0xe8, 0xbe, 0xa2, 0x13, 0x22, 0x8a, 0x43, 0x03, 0xed, 0x45, 0x00, 0x25, 0x2d, 0x21, 0xdc, 0x28, 0xa0, 0x42, 0x76, 0xa2, 0x98, 0x82, 0x8a, 0x82, 0x83, 0xb5, 0x25, 0x55, 0xc4, 0x2d, 0x25, 0x20, 0x0a, 0x2a, 0x80, 0x28, 0xa4, 0xd0, 0x05, 0x14, 0xba, 0x00, 0x51, 0x4d, 0x0c, 0x4a, 0x28, 0x10, 0x51, 0x48, 0x00, 0xd2, 0x53, 0x01, 0xd4, 0x95, 0x3b, 0x0c, 0x4a, 0x5a, 0xab, 0xe8, 0x01, 0x49, 0x48, 0x02, 0x96, 0x81, 0x09, 0x4b, 0x40, 0xc2, 0x92, 0x80, 0x0a, 0x28, 0x10, 0x52, 0x52, 0x01, 0x68, 0xaa, 0x4c, 0x02, 0x8a, 0x4c, 0x61, 0x49, 0x40, 0x85, 0xa4, 0xa0, 0x62, 0xd2, 0x50, 0xc0, 0x28, 0xa6, 0x04, 0xfd, 0x39, 0xa5, 0x23, 0xb1, 0xad, 0xb6, 0x29, 0x89, 0xcd, 0x2e, 0x72, 0x39, 0xa3, 0xa8, 0xb7, 0x17, 0x3b, 0x47, 0x19, 0xa3, 0xee, 0xd0, 0xb6, 0x0f, 0x20, 0x14, 0x50, 0xdf, 0x40, 0x13, 0xbd, 0x15, 0x1c, 0xc2, 0xd8, 0x4a, 0x75, 0x00, 0x27, 0x38, 0xa4, 0xcd, 0x3f, 0x30, 0x0a, 0x4a, 0x3a, 0x80, 0x51, 0x4a, 0xdd, 0x44, 0x14, 0x94, 0xb7, 0x43, 0x0c, 0xd2, 0x9a, 0x04, 0x27, 0x1d, 0xa9, 0x4f, 0x4a, 0x81, 0x8d, 0xa5, 0xaa, 0xb3, 0x60, 0x1d, 0x29, 0x28, 0x42, 0x0c, 0xd1, 0x54, 0x30, 0xea, 0x28, 0x3d, 0x6a, 0x40, 0x28, 0xa4, 0x21, 0x28, 0xa5, 0x61, 0x0b, 0x49, 0xda, 0x99, 0x41, 0x47, 0xb5, 0x02, 0x0a, 0x4a, 0x18, 0x5c, 0x28, 0xa6, 0x21, 0x45, 0x25, 0x41, 0x42, 0xd2, 0x55, 0x08, 0x4a, 0x29, 0x00, 0xb4, 0x50, 0x01, 0x45, 0x08, 0x62, 0x51, 0x4c, 0x42, 0xd1, 0x4a, 0xe0, 0x36, 0x96, 0x9b, 0x06, 0x06, 0x81, 0x40, 0xec, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x12, 0x96, 0x98, 0x82, 0x92, 0x80, 0x0a, 0x2a, 0x40, 0x28, 0xa6, 0x30, 0xa5, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x2d, 0x0c, 0x44, 0xff, 0x00, 0xef, 0x50, 0x79, 0xf6, 0xad, 0xca, 0x02, 0x4e, 0x68, 0xce, 0x3f, 0x1a, 0x3a, 0x00, 0x52, 0x9a, 0x00, 0x4a, 0x3b, 0x73, 0x49, 0x5c, 0x4c, 0x28, 0xe3, 0x27, 0x8a, 0x6f, 0xde, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x56, 0x00, 0xcd, 0x14, 0x00, 0x9d, 0x0d, 0x2d, 0x20, 0x12, 0x93, 0xa5, 0x00, 0x1f, 0x4a, 0x3b, 0x54, 0x5c, 0x03, 0xaf, 0x5a, 0x28, 0xbe, 0x80, 0x14, 0x52, 0x00, 0x14, 0x94, 0xc5, 0x60, 0xef, 0x49, 0x4f, 0xcc, 0x2e, 0x2d, 0x14, 0x6e, 0x21, 0x05, 0x2d, 0x21, 0x89, 0xde, 0x8a, 0x43, 0x0a, 0x3b, 0x55, 0x31, 0x05, 0x25, 0x48, 0x05, 0x2d, 0x30, 0xb0, 0x51, 0x48, 0x62, 0x51, 0x54, 0x21, 0x45, 0x25, 0x48, 0x05, 0x25, 0x00, 0x2d, 0x1d, 0xe9, 0x80, 0x51, 0x40, 0x09, 0x45, 0x00, 0x14, 0x52, 0x01, 0x29, 0x69, 0xb6, 0x02, 0x50, 0x28, 0x18, 0xb4, 0x54, 0x88, 0x28, 0xaa, 0x01, 0x29, 0x69, 0x0c, 0x4a, 0x29, 0x80, 0xb4, 0x95, 0x22, 0x16, 0x8a, 0x06, 0x25, 0x2d, 0x50, 0x84, 0xa2, 0xa4, 0x02, 0x8a, 0xa0, 0x27, 0xe3, 0x34, 0xbf, 0x4a, 0xd7, 0x52, 0xac, 0x1d, 0xa8, 0xcf, 0xcb, 0x46, 0xa1, 0x71, 0x39, 0xa7, 0x52, 0x60, 0x27, 0x7c, 0x51, 0xda, 0x85, 0x27, 0xb0, 0x05, 0x27, 0x6a, 0x42, 0x0a, 0x28, 0xdc, 0x42, 0x52, 0xf5, 0xa6, 0xf4, 0x18, 0x9f, 0x5a, 0x3b, 0xd2, 0xbd, 0xc0, 0x28, 0xa9, 0x00, 0xa4, 0xcd, 0x35, 0xb8, 0x00, 0xa2, 0x95, 0x80, 0x4e, 0xd4, 0x53, 0x5d, 0x80, 0x07, 0x5a, 0x5a, 0x5d, 0x44, 0x14, 0x94, 0x0c, 0x28, 0xa4, 0x48, 0x76, 0xa4, 0xa7, 0xe6, 0x50, 0x51, 0x52, 0x84, 0x14, 0x53, 0xb0, 0x09, 0x4b, 0x52, 0x02, 0x52, 0xd3, 0x01, 0x33, 0x41, 0xa1, 0x00, 0x51, 0x4c, 0x62, 0x51, 0x53, 0x60, 0x0a, 0x5a, 0xa1, 0x05, 0x14, 0xac, 0x21, 0x29, 0x68, 0x28, 0x4a, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x00, 0x28, 0xa6, 0x31, 0x29, 0x69, 0x88, 0x4a, 0x28, 0x01, 0x68, 0xa4, 0x21, 0x29, 0x68, 0x18, 0x94, 0xb4, 0x6e, 0x31, 0x28, 0xa4, 0x20, 0xa2, 0x98, 0xc2, 0x96, 0x90, 0x84, 0xa2, 0x80, 0x0a, 0x28, 0x02, 0x7a, 0x3d, 0xc5, 0x6e, 0x8a, 0x0a, 0x32, 0xdd, 0xcd, 0x2f, 0x21, 0x8a, 0x7a, 0x8a, 0x5e, 0xf4, 0xed, 0xa5, 0xc9, 0x10, 0x52, 0x7f, 0x0d, 0x48, 0xc3, 0x14, 0xa0, 0xe4, 0x50, 0xc4, 0x14, 0x53, 0xb8, 0x86, 0xd2, 0xfd, 0x69, 0x75, 0x18, 0x94, 0x52, 0x00, 0xcd, 0x25, 0x56, 0xc0, 0x2d, 0x1d, 0xba, 0xd4, 0x30, 0x0a, 0x4a, 0x60, 0x14, 0x94, 0xae, 0x02, 0xd1, 0x40, 0x84, 0xa2, 0x90, 0xc2, 0x92, 0x98, 0x82, 0x8e, 0xb4, 0x98, 0x05, 0x14, 0xac, 0x01, 0x45, 0x00, 0x14, 0x95, 0x40, 0x1d, 0xa8, 0xa4, 0x02, 0xd2, 0x51, 0x60, 0x0a, 0x28, 0xd8, 0x6c, 0x29, 0x69, 0x08, 0x4a, 0x4a, 0x18, 0x0b, 0x49, 0x40, 0x05, 0x14, 0x75, 0x00, 0xa2, 0x90, 0x05, 0x2d, 0x36, 0xc0, 0x29, 0x28, 0x40, 0x14, 0x50, 0x01, 0x49, 0x4c, 0x02, 0x96, 0x90, 0xc2, 0x8a, 0x42, 0x12, 0x94, 0xd1, 0xd4, 0x04, 0xa2, 0x98, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x00, 0x14, 0x53, 0xb8, 0x09, 0x4b, 0x53, 0x61, 0x96, 0x0f, 0xe9, 0x4b, 0xf8, 0x56, 0xe3, 0x7f, 0x10, 0x9e, 0xbe, 0x94, 0x63, 0x1d, 0x69, 0xd8, 0xa0, 0xf7, 0xa4, 0xa9, 0x49, 0x80, 0xb8, 0xa3, 0xb5, 0x1b, 0xb2, 0x58, 0x94, 0xbf, 0x51, 0x40, 0x84, 0x1e, 0xf4, 0x51, 0xb8, 0x09, 0xd6, 0x97, 0x15, 0x2c, 0x41, 0x49, 0x48, 0x61, 0x49, 0xd2, 0xa8, 0x04, 0xef, 0x4b, 0x54, 0xed, 0xb0, 0x85, 0xa4, 0xac, 0xc6, 0x21, 0xa5, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x27, 0x6a, 0xab, 0x80, 0xa2, 0x8a, 0x57, 0x24, 0x4a, 0x4a, 0x2c, 0x31, 0x7f, 0x9d, 0x1d, 0x68, 0x00, 0xa4, 0xa4, 0x31, 0x69, 0x3b, 0xd2, 0x10, 0xb4, 0x94, 0x5c, 0x04, 0xa5, 0xa0, 0x62, 0x52, 0xd5, 0x00, 0x51, 0x48, 0x56, 0x0f, 0xa5, 0x25, 0x20, 0x17, 0x34, 0x51, 0xb0, 0xec, 0x25, 0x14, 0x84, 0x1c, 0x51, 0x4c, 0x02, 0x8a, 0x77, 0x18, 0x51, 0x48, 0x42, 0x52, 0xd2, 0x01, 0x28, 0xa6, 0x01, 0x45, 0x00, 0x2d, 0x25, 0x2e, 0xa2, 0x0a, 0x29, 0xb1, 0x85, 0x14, 0x86, 0x14, 0x53, 0x10, 0x51, 0x4a, 0xe3, 0x0a, 0x28, 0x00, 0xa2, 0xa8, 0x02, 0x8a, 0x40, 0x58, 0xcf, 0xd2, 0x92, 0xb7, 0xe8, 0x31, 0x69, 0x33, 0xc7, 0x3d, 0x2a, 0x53, 0xd4, 0x63, 0xb8, 0xff, 0x00, 0x22, 0x8e, 0xf5, 0x4f, 0x41, 0x07, 0x6c, 0xd1, 0x53, 0xd0, 0x06, 0xd1, 0x49, 0x00, 0x6e, 0xf4, 0xa2, 0xa9, 0x08, 0x4a, 0x5f, 0x6a, 0x18, 0x08, 0x68, 0x3d, 0x6b, 0x30, 0x0a, 0x2a, 0x56, 0x82, 0x0a, 0x4a, 0xa1, 0x8b, 0x49, 0x40, 0x05, 0x27, 0x6a, 0x37, 0x24, 0x28, 0xa9, 0x18, 0x0a, 0x4e, 0xf4, 0xc6, 0x2d, 0x14, 0x08, 0x4a, 0x29, 0x00, 0x51, 0x4d, 0x8e, 0xc1, 0x49, 0x40, 0x07, 0x7a, 0x28, 0x10, 0x51, 0x4b, 0xcc, 0x61, 0x45, 0x00, 0x14, 0x53, 0xea, 0x01, 0x45, 0x2b, 0x80, 0x94, 0xb4, 0xc0, 0x4a, 0x2a, 0x58, 0x05, 0x14, 0xc1, 0x85, 0x14, 0x00, 0x51, 0x40, 0x84, 0xa5, 0xa0, 0x61, 0x45, 0x0c, 0x02, 0x92, 0x80, 0x0a, 0x29, 0x08, 0x28, 0xa0, 0x61, 0x4b, 0x40, 0x84, 0xa2, 0x81, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x53, 0x42, 0x0a, 0x4a, 0x06, 0x58, 0xcf, 0x34, 0x56, 0xa3, 0x03, 0xeb, 0x4b, 0xcf, 0xa5, 0x02, 0x0c, 0xfa, 0xf5, 0xa5, 0xa7, 0xd0, 0x62, 0x0f, 0x94, 0x60, 0xf5, 0xf6, 0xa2, 0x90, 0x07, 0xbf, 0x14, 0x9d, 0x0e, 0x69, 0x08, 0x4c, 0xfc, 0xb8, 0xed, 0x46, 0x45, 0x56, 0xc1, 0xd0, 0x77, 0xd2, 0x92, 0xa1, 0x82, 0x13, 0xde, 0x8e, 0xf4, 0xc0, 0x4f, 0xc6, 0x97, 0xa5, 0x26, 0x01, 0x9a, 0x4a, 0x00, 0x3b, 0x62, 0x93, 0x8a, 0x00, 0x3a, 0x51, 0x43, 0x10, 0x51, 0xd6, 0x95, 0x80, 0x33, 0x49, 0x48, 0x02, 0x8a, 0x40, 0x14, 0x53, 0xb5, 0x86, 0x1e, 0xf4, 0x53, 0x00, 0x14, 0x94, 0x80, 0x5a, 0x4a, 0x56, 0x00, 0xa2, 0x99, 0x21, 0x45, 0x00, 0x14, 0x50, 0xd0, 0xc4, 0xa2, 0x90, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x90, 0x82, 0x92, 0xa8, 0x05, 0xa2, 0x90, 0xc2, 0x92, 0x84, 0x20, 0xa2, 0x81, 0x85, 0x2d, 0x20, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x53, 0x18, 0x52, 0x52, 0x04, 0x2d, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x02, 0x7f, 0xe7, 0x49, 0x5b, 0xdf, 0xa1, 0x43, 0x85, 0x14, 0x84, 0xc3, 0x14, 0x77, 0xaa, 0xb8, 0xfa, 0x09, 0xed, 0x4b, 0xf5, 0xa5, 0x61, 0x58, 0x4a, 0x05, 0x24, 0x98, 0x07, 0x6a, 0x4a, 0x4c, 0x04, 0xcd, 0x2d, 0x16, 0x00, 0xa4, 0xa2, 0xfa, 0x00, 0x51, 0x4e, 0xf7, 0x06, 0x14, 0x66, 0x93, 0x01, 0x29, 0x7b, 0x54, 0xb0, 0x12, 0x8a, 0x04, 0x14, 0x1a, 0x2c, 0x30, 0xa2, 0x95, 0x84, 0x25, 0x19, 0xa6, 0x30, 0xa2, 0xa5, 0xea, 0x02, 0x52, 0xd0, 0x80, 0x4c, 0xd1, 0x4c, 0x02, 0x8a, 0x56, 0xd0, 0x02, 0x8a, 0x62, 0x0a, 0x29, 0x0c, 0x29, 0x28, 0x10, 0x51, 0x54, 0x01, 0x45, 0x21, 0x85, 0x2d, 0x48, 0x84, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x94, 0xa6, 0xa8, 0x04, 0xa5, 0xa0, 0x04, 0xa2, 0x90, 0x82, 0x8a, 0x06, 0x14, 0x52, 0x00, 0xa2, 0x98, 0x05, 0x14, 0xac, 0x21, 0x29, 0x69, 0x80, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x4a, 0x28, 0x10, 0x51, 0x48, 0x61, 0x4b, 0x42, 0x11, 0x3f, 0xae, 0x3f, 0x3c, 0x52, 0x0e, 0xb5, 0xd2, 0xf4, 0x2c, 0x77, 0x1d, 0xe9, 0x3d, 0xfb, 0xd4, 0xfc, 0x44, 0x8b, 0xef, 0x47, 0x7a, 0x4c, 0x62, 0x52, 0xd3, 0x60, 0xc3, 0xbd, 0x25, 0x17, 0x10, 0x99, 0xe3, 0xa5, 0x29, 0xa9, 0x01, 0x28, 0xa0, 0x02, 0x8e, 0xf5, 0x20, 0xc4, 0xa2, 0x9d, 0xc0, 0x3b, 0x51, 0xde, 0x86, 0x21, 0x3a, 0x52, 0xd2, 0xb0, 0xc2, 0x8a, 0x91, 0x09, 0x45, 0x50, 0xee, 0x25, 0x2d, 0x26, 0x24, 0xc4, 0xa2, 0x98, 0xc2, 0x8a, 0x01, 0x85, 0x02, 0x81, 0x05, 0x25, 0x48, 0x09, 0x4b, 0x4d, 0xea, 0x30, 0xa2, 0x95, 0xc4, 0x14, 0x50, 0xc0, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x08, 0x29, 0x29, 0x8c, 0x29, 0x69, 0x08, 0x28, 0xa0, 0x02, 0x92, 0x81, 0x85, 0x14, 0x00, 0xb4, 0x94, 0x80, 0x5a, 0x4a, 0x60, 0x14, 0x94, 0x00, 0xb4, 0x52, 0x00, 0xa4, 0xaa, 0x01, 0x68, 0xa9, 0x10, 0x51, 0x4c, 0x61, 0x49, 0x48, 0x02, 0x96, 0x81, 0x05, 0x25, 0x03, 0x16, 0x8a, 0x60, 0x4d, 0x47, 0xd0, 0xf1, 0x5b, 0xee, 0x01, 0x9a, 0x5e, 0x3d, 0x39, 0xa4, 0xd1, 0x42, 0xff, 0x00, 0xbc, 0x0d, 0x26, 0x7d, 0x72, 0x4d, 0x16, 0x10, 0x51, 0xdb, 0xaf, 0xe1, 0x45, 0x98, 0x80, 0xfb, 0xd1, 0xde, 0x93, 0x77, 0x00, 0xa2, 0x92, 0xb0, 0x0d, 0xa5, 0xa0, 0x02, 0x9b, 0x53, 0xb0, 0x0b, 0x45, 0x0f, 0x50, 0x12, 0x96, 0x9f, 0x51, 0x09, 0x4b, 0x40, 0xc4, 0xa4, 0xa9, 0x01, 0x68, 0xa2, 0xe2, 0x12, 0x8a, 0x60, 0x14, 0x52, 0xb8, 0xc4, 0xa2, 0x98, 0x82, 0x96, 0xa4, 0x04, 0xa2, 0x80, 0x0a, 0x29, 0xa1, 0x85, 0x14, 0xee, 0x20, 0xa4, 0xa9, 0x10, 0xb4, 0x94, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x3a, 0x80, 0x51, 0x54, 0x02, 0x51, 0x52, 0x31, 0x68, 0xa4, 0x20, 0xa2, 0x80, 0x12, 0x8a, 0xa0, 0x0a, 0x29, 0x0c, 0x28, 0xa6, 0x21, 0x29, 0x69, 0x00, 0x51, 0x48, 0x02, 0x92, 0xa8, 0x62, 0xd1, 0x52, 0x02, 0x51, 0x4c, 0x02, 0x96, 0x93, 0x10, 0x94, 0x50, 0x01, 0x45, 0x31, 0x8b, 0x49, 0x48, 0x0b, 0x14, 0x71, 0xda, 0xba, 0x2f, 0xa8, 0xb5, 0x13, 0xf0, 0xa0, 0x03, 0x4b, 0x41, 0x80, 0xfa, 0x73, 0x4e, 0x34, 0xdf, 0x98, 0x58, 0x4c, 0x77, 0xa4, 0xa0, 0x61, 0x4b, 0xd2, 0x96, 0x9b, 0x08, 0x29, 0x31, 0xcf, 0x15, 0x28, 0x40, 0x7a, 0x51, 0x49, 0xa1, 0x85, 0x26, 0x79, 0xa7, 0x60, 0xdc, 0x33, 0xed, 0x49, 0x49, 0x21, 0x05, 0x2d, 0x48, 0x09, 0x45, 0x31, 0x05, 0x15, 0x23, 0x0a, 0x4a, 0x43, 0x0a, 0x4a, 0xae, 0xa2, 0x16, 0x92, 0x98, 0x0b, 0x45, 0x20, 0x13, 0xa5, 0x14, 0x00, 0x51, 0x40, 0x0b, 0x49, 0x48, 0x04, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0xd2, 0xa4, 0x61, 0x45, 0x31, 0x06, 0x68, 0xa0, 0x62, 0x51, 0x4c, 0x41, 0x4b, 0x43, 0x00, 0xa4, 0xa4, 0x01, 0x45, 0x16, 0x18, 0x51, 0x48, 0x41, 0x45, 0x17, 0x00, 0xa2, 0x98, 0x05, 0x14, 0x80, 0x28, 0xa6, 0x08, 0x4a, 0x29, 0x0c, 0x5a, 0x4a, 0xa4, 0x20, 0xa2, 0x90, 0x05, 0x2d, 0x20, 0x12, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x00, 0x58, 0xf7, 0x34, 0x0a, 0xe8, 0x4b, 0xb8, 0x07, 0x7a, 0x1b, 0x35, 0x25, 0x59, 0x0b, 0xda, 0x90, 0x50, 0xd9, 0x22, 0xd1, 0xd3, 0xad, 0x08, 0x63, 0x7e, 0x94, 0xb4, 0x48, 0x57, 0x0e, 0x94, 0x94, 0x90, 0x85, 0xa4, 0xfc, 0x31, 0x4b, 0x71, 0x85, 0x25, 0x00, 0x2d, 0x25, 0x2f, 0x31, 0x09, 0x47, 0x5a, 0x63, 0x0a, 0x0d, 0x48, 0x09, 0x4b, 0x4c, 0x02, 0x92, 0xa5, 0x08, 0x28, 0xcd, 0x30, 0x0a, 0x2a, 0x6f, 0x70, 0x0a, 0x4a, 0xa0, 0x0a, 0x28, 0x40, 0x14, 0x50, 0x01, 0x49, 0x48, 0x05, 0xa4, 0xa6, 0x01, 0x45, 0x21, 0x85, 0x14, 0x5c, 0x41, 0x45, 0x31, 0x85, 0x14, 0x84, 0x14, 0x94, 0xc0, 0x29, 0x68, 0x01, 0x28, 0xa4, 0x01, 0xde, 0x8a, 0x06, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0xb8, 0x82, 0x8a, 0x00, 0x29, 0x28, 0x18, 0xb4, 0x94, 0x08, 0x5a, 0x4a, 0x00, 0x28, 0xa6, 0x01, 0x4b, 0x48, 0x62, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x13, 0x9e, 0x28, 0xae, 0x9d, 0xc0, 0x76, 0x3b, 0x75, 0xa4, 0x1c, 0x74, 0xac, 0xb6, 0x1e, 0xe1, 0xf5, 0xa3, 0xad, 0x34, 0x20, 0xa3, 0x8e, 0xd5, 0x43, 0x13, 0xbd, 0x28, 0xa0, 0x42, 0x52, 0x51, 0xa0, 0xc2, 0x8a, 0x97, 0xdc, 0x42, 0xf7, 0xa2, 0xa4, 0x42, 0x51, 0x4c, 0x02, 0x92, 0x90, 0x05, 0x27, 0x7a, 0x00, 0x29, 0x69, 0x00, 0x94, 0x66, 0x98, 0x82, 0x93, 0x14, 0x0c, 0x5a, 0x4a, 0x2e, 0x31, 0x69, 0x29, 0x5c, 0x41, 0x45, 0x03, 0x0a, 0x4a, 0x40, 0x2d, 0x25, 0x21, 0x05, 0x14, 0xc0, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x01, 0x29, 0x69, 0x0c, 0x4a, 0x29, 0xbd, 0x44, 0x14, 0x53, 0x00, 0xa2, 0xa4, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x4a, 0x40, 0x2d, 0x25, 0x02, 0x16, 0x8a, 0x00, 0x29, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0xc4, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0x48, 0x09, 0xcd, 0x19, 0xcf, 0xb5, 0x6c, 0x3b, 0x0b, 0xc6, 0x39, 0xa0, 0x9e, 0x6a, 0x6c, 0x0c, 0x4e, 0xb4, 0xbc, 0x77, 0xab, 0xf2, 0x18, 0x7b, 0x8a, 0x29, 0x08, 0x4a, 0x28, 0x00, 0xe3, 0x3c, 0xd0, 0x3d, 0xe9, 0x00, 0x51, 0xd6, 0x9d, 0xec, 0x21, 0x28, 0xa8, 0x63, 0x0a, 0x42, 0x7d, 0x69, 0x21, 0x05, 0x14, 0x00, 0x52, 0x53, 0xf3, 0x01, 0x69, 0x29, 0x74, 0x18, 0x51, 0x4e, 0xcc, 0x41, 0x45, 0x00, 0x82, 0x92, 0x81, 0x8b, 0x45, 0x40, 0x09, 0x45, 0x50, 0x98, 0x94, 0x50, 0xc1, 0x0b, 0x49, 0x52, 0x01, 0x45, 0x03, 0x0a, 0x4a, 0x60, 0x14, 0xb4, 0xc0, 0x4a, 0x29, 0x00, 0x52, 0xd0, 0x01, 0x49, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa2, 0xe3, 0x0a, 0x29, 0x08, 0x28, 0xa0, 0x02, 0x92, 0x98, 0xc5, 0xa2, 0x95, 0x80, 0x4a, 0x28, 0x01, 0x68, 0xa0, 0x04, 0xa2, 0x80, 0x0a, 0x29, 0x88, 0x28, 0xa4, 0x01, 0x45, 0x00, 0x14, 0x51, 0x61, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x09, 0xe8, 0xef, 0xed, 0x5b, 0x96, 0x2f, 0x1e, 0x99, 0xa3, 0x8a, 0x57, 0x00, 0xa2, 0x9e, 0x9d, 0x45, 0x60, 0xf7, 0xc5, 0x2f, 0x3f, 0x4a, 0x91, 0x0d, 0xfc, 0x28, 0xa6, 0x01, 0x45, 0x21, 0xa1, 0x3b, 0xd1, 0x48, 0x41, 0x47, 0x5a, 0x4c, 0x02, 0x86, 0xc6, 0x6a, 0x6c, 0x20, 0xa4, 0xaa, 0x00, 0xa3, 0x35, 0x23, 0x12, 0x8a, 0xa0, 0x0a, 0x4a, 0x9b, 0x88, 0x5a, 0x2a, 0xae, 0x31, 0x28, 0x34, 0xac, 0x84, 0x14, 0x53, 0x18, 0x51, 0x52, 0xc4, 0x14, 0x50, 0x24, 0x25, 0x14, 0xb7, 0x18, 0x51, 0x43, 0x18, 0x51, 0x4c, 0x02, 0x8a, 0x42, 0x0a, 0x4a, 0x06, 0x14, 0x53, 0xb8, 0x82, 0x8a, 0x43, 0x0a, 0x29, 0x88, 0x28, 0xa0, 0x02, 0x8a, 0x06, 0x25, 0x2d, 0x00, 0x25, 0x14, 0x80, 0x5a, 0x4a, 0x04, 0x14, 0x53, 0x00, 0xa5, 0xa4, 0x02, 0x51, 0x40, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x94, 0xb4, 0x0c, 0x28, 0xa0, 0x09, 0xe9, 0x47, 0x4a, 0xd9, 0x26, 0x0c, 0x4e, 0x29, 0x69, 0x94, 0x18, 0xf4, 0xa4, 0xa5, 0x70, 0xb8, 0xb4, 0x62, 0x91, 0x22, 0x51, 0x4f, 0x60, 0x17, 0xda, 0x9b, 0xea, 0x45, 0x00, 0x29, 0xa2, 0xa3, 0xa8, 0x09, 0x45, 0x27, 0xb8, 0x05, 0x25, 0x3b, 0xd8, 0x42, 0x8a, 0x29, 0x75, 0x18, 0x86, 0x83, 0x47, 0x90, 0x09, 0x45, 0x17, 0x10, 0x51, 0x49, 0x0c, 0x28, 0xa7, 0x64, 0x21, 0x3a, 0x8a, 0x2a, 0x46, 0x14, 0x55, 0x00, 0x51, 0x48, 0x42, 0x52, 0xe6, 0x81, 0x89, 0x45, 0x20, 0x0a, 0x28, 0x00, 0xa4, 0xa6, 0x01, 0x4b, 0x4c, 0x42, 0x51, 0x48, 0x61, 0x47, 0x7a, 0x40, 0x14, 0x50, 0x01, 0x45, 0x30, 0x0a, 0x29, 0x80, 0x51, 0x48, 0x04, 0xa5, 0xa0, 0x41, 0x49, 0x40, 0x0b, 0x45, 0x20, 0x0a, 0x4a, 0x06, 0x14, 0xb4, 0x00, 0x94, 0x53, 0x10, 0x51, 0x48, 0x02, 0x8a, 0x63, 0x12, 0x96, 0x90, 0x05, 0x25, 0x02, 0x16, 0x8a, 0x2e, 0x30, 0xa2, 0x80, 0x45, 0x8a, 0x4a, 0xda, 0xe5, 0x06, 0x29, 0x68, 0x24, 0x28, 0xa0, 0x62, 0x7f, 0x4a, 0x5a, 0x00, 0x5f, 0xc6, 0x9b, 0xf8, 0x54, 0x8a, 0xe1, 0xd2, 0x8e, 0x28, 0x40, 0x14, 0x99, 0xa9, 0xf3, 0x00, 0xa2, 0x81, 0x01, 0xef, 0x49, 0x4c, 0x61, 0x45, 0x01, 0x70, 0xa4, 0xa4, 0x01, 0x45, 0x31, 0x05, 0x15, 0x00, 0x25, 0x15, 0x48, 0x61, 0x45, 0x20, 0x0a, 0x29, 0x88, 0x4a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x06, 0x2d, 0x14, 0x00, 0x94, 0x52, 0xb0, 0x0b, 0x45, 0x21, 0x09, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x42, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x00, 0x5a, 0x4a, 0x06, 0x14, 0xb4, 0x00, 0x94, 0x53, 0x10, 0x51, 0x48, 0x02, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x08, 0x41, 0x45, 0x03, 0x0a, 0x4a, 0x00, 0x5a, 0x29, 0x80, 0x94, 0x52, 0x10, 0x52, 0xd0, 0x02, 0x51, 0x42, 0x19, 0x63, 0xf0, 0xa3, 0x8a, 0xd9, 0x68, 0x86, 0x03, 0x34, 0xb4, 0x86, 0xc4, 0xa2, 0x84, 0x98, 0xba, 0x8b, 0xda, 0x8e, 0xd4, 0x00, 0x52, 0x53, 0x62, 0x0a, 0x2a, 0x76, 0x00, 0xa4, 0xc5, 0x00, 0x14, 0x94, 0x00, 0x51, 0x52, 0x20, 0xa4, 0xaa, 0x43, 0x17, 0xa7, 0xbd, 0x14, 0x79, 0x80, 0x94, 0x54, 0x88, 0x29, 0x28, 0x18, 0xb4, 0x94, 0x08, 0x28, 0xa2, 0xe3, 0x0a, 0x28, 0x15, 0x84, 0xa2, 0x93, 0x00, 0xa2, 0x95, 0xc0, 0x28, 0xa0, 0x02, 0x92, 0xaa, 0xe3, 0x16, 0x93, 0x34, 0x98, 0x85, 0xa4, 0xa0, 0x02, 0x96, 0x90, 0x09, 0x45, 0x31, 0x85, 0x14, 0x08, 0x29, 0x29, 0x00, 0x52, 0xd0, 0x02, 0x51, 0x4f, 0xa0, 0xc2, 0x96, 0x90, 0x05, 0x25, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0xc4, 0x14, 0x52, 0x00, 0xa4, 0xa0, 0x61, 0x4b, 0x40, 0x05, 0x14, 0x30, 0x12, 0x8a, 0x00, 0x5a, 0x4a, 0x04, 0x14, 0x50, 0x05, 0x8f, 0xad, 0x06, 0xb6, 0x2d, 0xad, 0x40, 0x71, 0x47, 0xa9, 0xeb, 0x43, 0x42, 0x17, 0xd8, 0x7d, 0xda, 0x4f, 0x6a, 0x7e, 0x62, 0x0a, 0x5a, 0x96, 0x86, 0x27, 0x7a, 0x28, 0xd0, 0x18, 0x1e, 0x68, 0xa2, 0xe2, 0x13, 0xbd, 0x2d, 0x20, 0x12, 0x8a, 0x00, 0x29, 0x29, 0x75, 0x00, 0xa2, 0x86, 0x01, 0x49, 0x47, 0x5b, 0x00, 0x51, 0x48, 0x41, 0x45, 0x1d, 0x40, 0x4a, 0x29, 0x0c, 0x5a, 0x4a, 0x04, 0x14, 0x51, 0x71, 0x85, 0x25, 0x02, 0x0a, 0x29, 0xd8, 0x02, 0x8a, 0x40, 0x14, 0x50, 0x31, 0x29, 0x69, 0xb1, 0x09, 0x46, 0x69, 0x31, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x21, 0x09, 0x4b, 0x40, 0x09, 0x45, 0x00, 0x14, 0xb4, 0x0c, 0x4a, 0x29, 0x88, 0x28, 0xa5, 0xb0, 0x05, 0x14, 0x0c, 0x28, 0xa6, 0x01, 0x45, 0x2b, 0x80, 0x51, 0x4c, 0x41, 0x45, 0x21, 0x89, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x58, 0x34, 0xa2, 0xb5, 0x1b, 0x0a, 0x3f, 0x4a, 0x02, 0xe1, 0xcf, 0xe7, 0x47, 0xe9, 0x54, 0x02, 0x52, 0xd0, 0x20, 0xa4, 0x34, 0x80, 0x29, 0x2a, 0x58, 0x0b, 0xde, 0x8a, 0x57, 0x10, 0x94, 0x50, 0x30, 0xa4, 0x34, 0x05, 0x82, 0x93, 0x9a, 0x5e, 0x4c, 0x02, 0x8a, 0x00, 0x28, 0xa6, 0x01, 0x49, 0x48, 0x42, 0x8a, 0x4a, 0x96, 0x01, 0x49, 0x54, 0x80, 0x29, 0x68, 0xb0, 0xd8, 0x94, 0x52, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x00, 0x51, 0x42, 0x60, 0x14, 0x50, 0x31, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x15, 0x5d, 0x00, 0x28, 0xa4, 0x21, 0x69, 0x29, 0x00, 0x51, 0x40, 0x05, 0x14, 0xc6, 0x14, 0x52, 0x00, 0xa2, 0x81, 0x05, 0x25, 0x03, 0x16, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x29, 0x28, 0x01, 0x69, 0x28, 0x00, 0xa2, 0x81, 0x0b, 0x49, 0x40, 0x05, 0x2d, 0x00, 0x4f, 0xf8, 0x51, 0xf4, 0xad, 0x99, 0x57, 0x0c, 0x51, 0x4d, 0x08, 0x38, 0x3c, 0x51, 0x8e, 0xdd, 0xe9, 0x8c, 0x06, 0x7b, 0xd1, 0x49, 0xb1, 0x01, 0xa3, 0xad, 0x21, 0x8b, 0x4d, 0xa9, 0x62, 0xd8, 0x4a, 0x3a, 0x52, 0xb0, 0xae, 0x2d, 0x14, 0x90, 0xc4, 0xef, 0x45, 0x50, 0x08, 0x69, 0x6a, 0x5f, 0x71, 0x58, 0x4a, 0x29, 0x8c, 0x28, 0xe9, 0x52, 0x01, 0x48, 0x6a, 0x84, 0x2d, 0x25, 0x20, 0x12, 0x8a, 0x06, 0x2d, 0x25, 0x2b, 0x88, 0x28, 0xa0, 0x61, 0x49, 0x4c, 0x42, 0xd1, 0x52, 0x02, 0x52, 0xd5, 0x0c, 0x4a, 0x29, 0x00, 0x51, 0x4d, 0x08, 0x28, 0xa4, 0x30, 0xa2, 0x98, 0x84, 0xa5, 0xa4, 0x80, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x84, 0x14, 0x50, 0xc6, 0x14, 0x50, 0x01, 0x45, 0x1a, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x60, 0x14, 0x52, 0xdc, 0x61, 0x45, 0x31, 0x09, 0x45, 0x20, 0x0a, 0x28, 0x18, 0xb4, 0x94, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x53, 0x02, 0xcf, 0x7a, 0x4a, 0xdd, 0xbb, 0xb1, 0x87, 0xf4, 0xa3, 0x9a, 0x5b, 0x08, 0x05, 0x14, 0x5f, 0x51, 0xd8, 0x28, 0x35, 0x37, 0xbb, 0x00, 0xfa, 0xd2, 0xd3, 0xb8, 0x34, 0x25, 0x15, 0x3a, 0x88, 0x29, 0x28, 0xd8, 0x42, 0x51, 0x48, 0x61, 0x45, 0x31, 0x05, 0x1c, 0x54, 0x83, 0x62, 0x51, 0x54, 0x30, 0xa2, 0xa0, 0x04, 0xa5, 0xa1, 0x80, 0x94, 0x50, 0x20, 0xa4, 0xa0, 0x61, 0x4b, 0x40, 0x09, 0xda, 0x8a, 0x62, 0x0a, 0x29, 0x00, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x29, 0x28, 0x60, 0x14, 0x52, 0x00, 0xa2, 0x98, 0x05, 0x25, 0x20, 0x16, 0x92, 0x98, 0x31, 0x69, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa4, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x00, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x96, 0x3f, 0x1a, 0x4a, 0xdb, 0xd0, 0xab, 0x75, 0x16, 0x8f, 0x4a, 0x44, 0x85, 0x2f, 0xb5, 0x3d, 0xc0, 0x69, 0xf4, 0xa7, 0x1e, 0x4d, 0x3b, 0x68, 0x02, 0x51, 0x52, 0x80, 0x28, 0xa0, 0x04, 0xa0, 0xd4, 0x85, 0x84, 0xa2, 0xa8, 0x02, 0x97, 0x23, 0xb5, 0x2b, 0x00, 0xda, 0x5a, 0x04, 0x25, 0x14, 0x98, 0xc2, 0x8a, 0x35, 0x10, 0x94, 0xb4, 0x98, 0x05, 0x21, 0xa0, 0x62, 0x52, 0xd2, 0x62, 0x10, 0xd1, 0x40, 0xc4, 0xa5, 0xaa, 0xd0, 0x41, 0x45, 0x2d, 0xc6, 0x25, 0x2d, 0x48, 0x84, 0xa2, 0x9e, 0xc3, 0x0a, 0x28, 0x00, 0xa2, 0x90, 0x05, 0x14, 0xc0, 0x29, 0x29, 0x00, 0xb4, 0x94, 0xc4, 0x14, 0x52, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x09, 0x45, 0x02, 0x16, 0x92, 0x81, 0x85, 0x14, 0x08, 0x29, 0x68, 0x01, 0x28, 0xa6, 0xc6, 0x14, 0x50, 0x01, 0x45, 0x20, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x2c, 0x52, 0x9c, 0x81, 0x9a, 0xde, 0xe9, 0xb1, 0xbd, 0xc6, 0xf1, 0x4b, 0x93, 0x48, 0x57, 0x0c, 0xd1, 0xc7, 0x5a, 0x9e, 0x5e, 0xa0, 0x00, 0xf3, 0xd2, 0x93, 0xa5, 0x30, 0x0a, 0x33, 0x4a, 0xf7, 0x00, 0xcd, 0x03, 0xa6, 0x68, 0x18, 0x52, 0xd3, 0x10, 0x9d, 0xe8, 0xa1, 0xea, 0x02, 0x52, 0xfe, 0x14, 0x81, 0x89, 0x49, 0x40, 0x58, 0x5e, 0xb4, 0x94, 0xac, 0x16, 0x0a, 0x29, 0x80, 0x0a, 0x28, 0x0b, 0x09, 0x45, 0x48, 0x05, 0x15, 0x40, 0x14, 0x54, 0x80, 0x52, 0x50, 0x80, 0x5a, 0x4a, 0x2c, 0x01, 0x45, 0x16, 0x01, 0x29, 0x69, 0xd8, 0x02, 0x92, 0x95, 0x80, 0x29, 0x69, 0x00, 0x52, 0x53, 0xb0, 0x05, 0x18, 0xa0, 0x02, 0x8a, 0x2c, 0x01, 0x45, 0x16, 0x00, 0xa4, 0xa5, 0x60, 0xb0, 0xb4, 0x94, 0xc0, 0x28, 0xa5, 0x60, 0x0a, 0x29, 0x00, 0x51, 0x54, 0x01, 0x45, 0x20, 0x0a, 0x29, 0xda, 0xe0, 0x14, 0x52, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x2c, 0x01, 0x45, 0x00, 0x25, 0x2d, 0x20, 0x12, 0x96, 0x98, 0x09, 0x4b, 0x40, 0x13, 0xf4, 0xa4, 0xad, 0x36, 0x41, 0xb8, 0x51, 0xdb, 0x14, 0xb9, 0x47, 0x61, 0x68, 0xa7, 0xb0, 0x05, 0x1d, 0x0d, 0x55, 0x84, 0x1d, 0x69, 0x2a, 0x7c, 0x80, 0x28, 0xa4, 0x30, 0xa2, 0x98, 0x82, 0x92, 0x8b, 0x80, 0x51, 0xef, 0x48, 0x04, 0xa2, 0xa4, 0x02, 0x8a, 0x3a, 0x05, 0xc2, 0x8a, 0x77, 0xb0, 0x05, 0x25, 0x20, 0xb8, 0xb4, 0x94, 0x00, 0x51, 0x48, 0x04, 0xa2, 0x98, 0x05, 0x14, 0x00, 0x66, 0x8a, 0x40, 0x14, 0x50, 0xc0, 0x29, 0x28, 0x00, 0xa0, 0x53, 0x00, 0xa2, 0x90, 0x82, 0x8a, 0x43, 0x0a, 0x28, 0x00, 0xa4, 0xa0, 0x05, 0xa4, 0xa6, 0x01, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa4, 0xa4, 0x30, 0xa5, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x4a, 0x29, 0x80, 0x52, 0xd0, 0x20, 0xa4, 0xa4, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x27, 0x3c, 0xd2, 0xd6, 0xb7, 0x18, 0x94, 0x67, 0xd6, 0x8d, 0xc0, 0x5a, 0x0f, 0x5a, 0x62, 0x0c, 0xd1, 0x4b, 0x50, 0xb0, 0x52, 0x54, 0xb0, 0x03, 0xd6, 0x92, 0x98, 0xc2, 0x96, 0x90, 0xae, 0x21, 0xa2, 0x9a, 0x00, 0xa2, 0x80, 0x12, 0x8a, 0x97, 0xa8, 0x05, 0x14, 0x58, 0x04, 0xa2, 0x9e, 0xe0, 0x14, 0x95, 0x20, 0x2d, 0x14, 0x00, 0x52, 0x52, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x77, 0x10, 0x52, 0x52, 0x18, 0x52, 0xd5, 0x00, 0x94, 0x50, 0x20, 0xa2, 0xa4, 0x41, 0x49, 0x40, 0xc5, 0xa2, 0x81, 0x85, 0x14, 0x08, 0x29, 0x29, 0x80, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x4a, 0x57, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x60, 0x25, 0x2d, 0x20, 0x0a, 0x29, 0x81, 0x39, 0xa2, 0xac, 0x76, 0x0e, 0xb4, 0x53, 0x18, 0xa2, 0x93, 0x9a, 0x68, 0x05, 0x1d, 0x28, 0xa0, 0x90, 0xa2, 0xa2, 0xe0, 0x25, 0x14, 0xc0, 0x29, 0x29, 0x05, 0x84, 0xa5, 0xaa, 0x00, 0xa3, 0x1e, 0xd5, 0x9f, 0x41, 0x09, 0xd6, 0x8a, 0x77, 0x18, 0x51, 0x4c, 0x04, 0xa5, 0xa5, 0x71, 0x09, 0x49, 0x4c, 0x05, 0xa2, 0x90, 0xc4, 0xa2, 0x95, 0xc4, 0x14, 0x51, 0xb8, 0x01, 0x34, 0x53, 0x00, 0xa2, 0x90, 0x09, 0x45, 0x03, 0x0a, 0x29, 0x08, 0x4a, 0x5a, 0x60, 0x14, 0x66, 0x90, 0x58, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x60, 0x25, 0x2d, 0x20, 0x12, 0x96, 0x80, 0x12, 0x96, 0x81, 0x89, 0x45, 0x31, 0x05, 0x14, 0x80, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x85, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4e, 0x7a, 0x51, 0xda, 0xb7, 0x28, 0x3e, 0x94, 0x71, 0xef, 0x4c, 0x41, 0x4e, 0xa9, 0x01, 0xb4, 0xb4, 0xc4, 0x27, 0xe1, 0x45, 0x26, 0x3b, 0x85, 0x1d, 0xe9, 0x08, 0x28, 0xa9, 0xea, 0x02, 0x52, 0x73, 0x43, 0x01, 0x71, 0x4a, 0x38, 0x6a, 0x42, 0x1b, 0xd2, 0x8a, 0x10, 0xc4, 0x34, 0xb4, 0x58, 0x04, 0xa2, 0x98, 0x82, 0x92, 0x86, 0xc6, 0x2d, 0x25, 0x48, 0x82, 0x8a, 0x12, 0x18, 0x51, 0x4c, 0x41, 0x45, 0x48, 0x09, 0x45, 0x31, 0x85, 0x14, 0x08, 0x28, 0xa4, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x10, 0x94, 0x50, 0x01, 0x40, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x29, 0x8c, 0x29, 0x29, 0x00, 0x51, 0x4c, 0x02, 0x8a, 0x40, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0xb4, 0x08, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x09, 0x4b, 0x40, 0x13, 0xe6, 0x96, 0xb4, 0xb8, 0x75, 0x13, 0x22, 0x8e, 0xf5, 0x6b, 0x51, 0x8b, 0xc7, 0x6a, 0x4a, 0xa6, 0x01, 0x4b, 0x51, 0xcc, 0x02, 0x51, 0x9a, 0x62, 0xb0, 0x94, 0xb5, 0x37, 0x00, 0xa4, 0xa4, 0x01, 0x45, 0x27, 0xdc, 0x04, 0xa5, 0xa6, 0x02, 0x52, 0xd2, 0x01, 0x28, 0xa4, 0x02, 0x51, 0x40, 0x05, 0x14, 0x9e, 0xa0, 0x14, 0x94, 0x02, 0x0a, 0x28, 0x60, 0x25, 0x2d, 0x3d, 0x01, 0x89, 0x45, 0x21, 0x20, 0xa2, 0x81, 0x85, 0x14, 0x80, 0x28, 0xa0, 0x41, 0x45, 0x30, 0x0a, 0x29, 0x00, 0x94, 0x53, 0x00, 0xa2, 0x8b, 0x8c, 0x28, 0xa6, 0x20, 0xa4, 0xa9, 0x18, 0x52, 0xd3, 0xb0, 0x82, 0x92, 0x90, 0x05, 0x2d, 0x03, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x2c, 0x02, 0x51, 0x40, 0x85, 0xa2, 0x81, 0x89, 0x45, 0x00, 0x2d, 0x14, 0xc0, 0x9f, 0x14, 0xbd, 0xaa, 0x86, 0x1c, 0xfe, 0x14, 0x55, 0xa6, 0x98, 0x84, 0xa2, 0xa8, 0x62, 0x8e, 0x3a, 0x52, 0x54, 0xdd, 0x08, 0x28, 0xa0, 0x04, 0xa5, 0xa0, 0x04, 0x34, 0xb5, 0x20, 0x25, 0x15, 0x37, 0x01, 0x29, 0x4d, 0x30, 0x1b, 0x47, 0xb5, 0x48, 0x0b, 0x49, 0x4f, 0xa0, 0x07, 0x7a, 0x28, 0x40, 0x14, 0x53, 0x0b, 0x85, 0x15, 0x20, 0x25, 0x14, 0xc4, 0x14, 0x50, 0x30, 0xa4, 0xa0, 0x41, 0x4b, 0x53, 0x61, 0x89, 0x45, 0x00, 0x14, 0x50, 0x21, 0x29, 0x69, 0x80, 0x94, 0x50, 0x02, 0xd2, 0x52, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x00, 0x28, 0xa6, 0x30, 0xa4, 0xa4, 0x01, 0x4b, 0x40, 0x09, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x98, 0xc2, 0x8a, 0x42, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x28, 0xa0, 0x62, 0x52, 0xd0, 0x05, 0x8f, 0xf3, 0xd2, 0x93, 0xad, 0x6a, 0xc0, 0x29, 0x6a, 0x96, 0xa5, 0x07, 0x6a, 0x3b, 0x54, 0x8a, 0xc0, 0x28, 0xa3, 0x46, 0x21, 0x29, 0x6a, 0xb6, 0x0b, 0x09, 0x49, 0x51, 0x70, 0x0a, 0x0d, 0x34, 0x01, 0xda, 0x92, 0x96, 0x80, 0x14, 0xb5, 0x3d, 0x44, 0x25, 0x14, 0xf4, 0x18, 0x94, 0x52, 0x00, 0xa2, 0x86, 0xc0, 0x29, 0x28, 0xb0, 0x82, 0x8a, 0x2c, 0x01, 0x45, 0x0c, 0x02, 0x92, 0x80, 0x16, 0x8a, 0x90, 0x12, 0x8a, 0x01, 0x85, 0x14, 0xc0, 0x28, 0xa0, 0x04, 0xa2, 0x90, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x4a, 0x5a, 0x00, 0x4a, 0x28, 0x01, 0x69, 0x28, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x92, 0x81, 0x0b, 0x45, 0x03, 0x0a, 0x4a, 0x00, 0x5a, 0x4a, 0x00, 0xb1, 0xf8, 0x52, 0x56, 0xdb, 0x0c, 0x5c, 0x8e, 0x98, 0xa5, 0xa4, 0x02, 0x52, 0xd1, 0x21, 0x05, 0x14, 0xc6, 0x25, 0x14, 0x08, 0x05, 0x15, 0x3d, 0x00, 0x4a, 0x2a, 0x77, 0x00, 0xe6, 0x93, 0xbd, 0x08, 0x05, 0xa6, 0xd5, 0x74, 0x04, 0x2d, 0x21, 0xa3, 0x70, 0x0a, 0x2a, 0x40, 0x28, 0xa6, 0x20, 0xa2, 0xa6, 0xe0, 0x14, 0x94, 0x20, 0x0a, 0x29, 0xb0, 0x0a, 0x4a, 0x40, 0x2d, 0x25, 0x00, 0x14, 0x52, 0x18, 0x94, 0xb4, 0xc4, 0x14, 0x50, 0x31, 0x29, 0x69, 0x00, 0x94, 0x50, 0x80, 0x28, 0xa0, 0x02, 0x8a, 0x60, 0x14, 0x52, 0x10, 0x51, 0x40, 0x09, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x04, 0x14, 0x53, 0x18, 0x51, 0x40, 0x05, 0x14, 0x84, 0x14, 0x50, 0x30, 0xa4, 0xa6, 0x01, 0x45, 0x20, 0x16, 0x8a, 0x00, 0x29, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x96, 0x80, 0x27, 0xed, 0x49, 0xfc, 0xeb, 0x6e, 0x50, 0x1d, 0x8a, 0x2a, 0x47, 0x71, 0x28, 0xa7, 0xa0, 0xc0, 0xd1, 0x54, 0x20, 0xa2, 0x90, 0x82, 0x8a, 0x86, 0x80, 0x4c, 0xd1, 0x4e, 0xc8, 0x41, 0x45, 0x21, 0x89, 0x45, 0x00, 0x14, 0x52, 0x01, 0x28, 0xa0, 0x41, 0x45, 0x00, 0x14, 0x94, 0x0d, 0x05, 0x14, 0xac, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa4, 0xa4, 0x01, 0x45, 0x30, 0x0a, 0x28, 0x00, 0xa4, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x90, 0xc2, 0x8a, 0x62, 0x0a, 0x4a, 0x40, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x31, 0x69, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x92, 0x80, 0x16, 0x8a, 0x04, 0x25, 0x14, 0x00, 0x51, 0x40, 0x0b, 0x49, 0x40, 0xc5, 0xa4, 0xa0, 0x09, 0xf3, 0x45, 0x6c, 0x31, 0x7b, 0x52, 0xd4, 0xe8, 0x21, 0x28, 0xe9, 0xd6, 0x98, 0xc2, 0x96, 0x9d, 0xc4, 0x26, 0x68, 0xa4, 0x08, 0x4a, 0x5e, 0xd4, 0xae, 0x02, 0x51, 0x4d, 0x87, 0x50, 0xa4, 0xa4, 0x01, 0x49, 0x4b, 0xa8, 0x85, 0xa4, 0xa4, 0x3b, 0x85, 0x14, 0x20, 0x0a, 0x4a, 0x4c, 0x05, 0xa4, 0xa0, 0x41, 0x4b, 0x40, 0xc4, 0xa4, 0xa7, 0xd0, 0x02, 0x8a, 0x04, 0x2d, 0x25, 0x20, 0x0a, 0x29, 0x00, 0x51, 0x4c, 0x62, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x42, 0x51, 0x4c, 0x62, 0xd2, 0x52, 0x10, 0xb4, 0x94, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x12, 0x96, 0x80, 0x0a, 0x28, 0x10, 0x94, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x16, 0x92, 0x80, 0x16, 0x92, 0x81, 0x05, 0x14, 0x01, 0x63, 0x14, 0x56, 0xf7, 0x28, 0x28, 0xa8, 0x96, 0xa2, 0x61, 0xdf, 0xa5, 0x2f, 0xd0, 0x53, 0xb0, 0xc4, 0x3d, 0x28, 0xe2, 0x9f, 0x40, 0x0a, 0x2a, 0x44, 0x25, 0x2d, 0x30, 0x12, 0x8a, 0x4c, 0x03, 0x34, 0x94, 0x96, 0xc0, 0x2e, 0x68, 0xa9, 0x01, 0x29, 0x2a, 0xd0, 0x05, 0x14, 0x80, 0x28, 0xa4, 0x02, 0x52, 0xd2, 0x01, 0x29, 0x69, 0x80, 0x94, 0x52, 0x10, 0x94, 0xb4, 0x0c, 0x4a, 0x28, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x42, 0x52, 0xd2, 0x01, 0x28, 0xa0, 0x61, 0x45, 0x1d, 0x44, 0x14, 0x53, 0xb8, 0xc2, 0x92, 0x90, 0x82, 0x8a, 0x2e, 0x31, 0x68, 0xa0, 0x42, 0x51, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x10, 0x52, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x0b, 0x49, 0x40, 0xc5, 0xa4, 0xa0, 0x0b, 0x14, 0x66, 0xb5, 0x2b, 0x40, 0xa2, 0x90, 0x82, 0x8a, 0x16, 0xe2, 0xe8, 0x1d, 0x28, 0xa7, 0xb8, 0x21, 0x29, 0x73, 0x47, 0x40, 0x0a, 0x4a, 0x40, 0x14, 0x76, 0xa0, 0x62, 0x0a, 0x5a, 0x91, 0x09, 0x45, 0x08, 0x02, 0x83, 0x40, 0x09, 0x45, 0x31, 0x05, 0x15, 0x37, 0x01, 0x28, 0xa0, 0x05, 0xa4, 0xa2, 0xe0, 0x14, 0x53, 0x18, 0x52, 0x52, 0x00, 0xa2, 0x90, 0x05, 0x15, 0x42, 0x0a, 0x4a, 0x00, 0x29, 0x69, 0x00, 0x94, 0x50, 0x01, 0x45, 0x21, 0x89, 0x4b, 0x40, 0x82, 0x8a, 0x00, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x06, 0x2d, 0x25, 0x02, 0x0a, 0x4a, 0x06, 0x2d, 0x14, 0x00, 0x94, 0xb4, 0x00, 0x51, 0x40, 0x09, 0x4b, 0x40, 0x05, 0x14, 0x08, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x96, 0x81, 0x89, 0x45, 0x02, 0x16, 0x92, 0x84, 0x32, 0xc6, 0x73, 0x47, 0xe1, 0x5a, 0xdc, 0x04, 0xfd, 0x68, 0xa2, 0xe3, 0x16, 0x96, 0x95, 0xf5, 0x00, 0xa4, 0xaa, 0x10, 0x66, 0x8a, 0x40, 0x14, 0x52, 0x01, 0x28, 0xa4, 0x02, 0x52, 0xd0, 0x02, 0x1a, 0x0d, 0x20, 0x12, 0x96, 0x9b, 0x01, 0x28, 0xa4, 0x01, 0x45, 0x02, 0x12, 0x96, 0x90, 0xc2, 0x92, 0x90, 0x82, 0x8a, 0x60, 0x14, 0x94, 0x74, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x48, 0x04, 0xa5, 0xa0, 0x42, 0x51, 0x4c, 0x62, 0xd2, 0x52, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x00, 0x51, 0x4c, 0x62, 0x51, 0x48, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x42, 0x12, 0x8a, 0x63, 0x0a, 0x5a, 0x00, 0x4a, 0x28, 0x00, 0xa2, 0x81, 0x05, 0x14, 0xc0, 0x28, 0xa4, 0x01, 0x45, 0x03, 0x2c, 0x1a, 0x4a, 0xd7, 0xa0, 0x0b, 0x45, 0x30, 0x13, 0x3e, 0xd4, 0x53, 0xb0, 0x05, 0x2d, 0x20, 0xb8, 0x94, 0x53, 0xbe, 0x80, 0x14, 0x54, 0xd8, 0x02, 0x92, 0x97, 0x40, 0x0a, 0x5a, 0x40, 0x25, 0x19, 0xa0, 0x04, 0xa5, 0xa5, 0x60, 0x13, 0x14, 0x1a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x20, 0x12, 0x8a, 0x63, 0x0a, 0x28, 0x62, 0x12, 0x8a, 0x06, 0x14, 0x52, 0x10, 0x51, 0x4c, 0x04, 0xa5, 0xa9, 0x60, 0x25, 0x2d, 0x03, 0x12, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x92, 0x84, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x51, 0x40, 0x84, 0xa2, 0x80, 0x16, 0x8a, 0x00, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x96, 0x81, 0x85, 0x25, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x04, 0xff, 0x00, 0x5a, 0x2b, 0x50, 0x16, 0x92, 0x81, 0x85, 0x2d, 0x50, 0x07, 0xe1, 0x49, 0x48, 0x48, 0x5f, 0xc2, 0x8a, 0x4c, 0x04, 0xa2, 0x90, 0x20, 0xa4, 0xa5, 0x6b, 0x00, 0xb4, 0x50, 0x02, 0x52, 0x51, 0x70, 0x0a, 0x29, 0x00, 0x51, 0x45, 0x80, 0x28, 0xa0, 0x04, 0xa2, 0x90, 0x05, 0x14, 0x00, 0x94, 0xb4, 0x80, 0x29, 0x29, 0x88, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x12, 0x96, 0x90, 0xc4, 0xa2, 0x9d, 0xc4, 0x14, 0x53, 0x00, 0xa2, 0xa4, 0x61, 0x49, 0x40, 0x05, 0x2d, 0x30, 0x0a, 0x4a, 0x04, 0x14, 0x52, 0x00, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x52, 0x50, 0x21, 0x68, 0xa0, 0x02, 0x8a, 0x00, 0x29, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x80, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x22, 0xc5, 0x27, 0x7a, 0xd0, 0x6c, 0x28, 0xaa, 0x00, 0x3d, 0xa8, 0xa0, 0x05, 0xa2, 0x8e, 0x83, 0x0a, 0x4a, 0x95, 0xb8, 0x82, 0x8a, 0x00, 0x4a, 0x5a, 0x64, 0x85, 0x25, 0x49, 0x41, 0x45, 0x26, 0x02, 0x51, 0x4c, 0x02, 0x92, 0x80, 0x16, 0x8a, 0x90, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x00, 0x69, 0x28, 0x43, 0x0a, 0x29, 0x88, 0x5a, 0x4a, 0x43, 0x0a, 0x28, 0xb0, 0x05, 0x25, 0x00, 0x14, 0x52, 0x10, 0xb4, 0x94, 0x0c, 0x28, 0xa0, 0x41, 0x49, 0x40, 0xc5, 0xa2, 0x80, 0x12, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x00, 0x28, 0xa0, 0x04, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x9f, 0x14, 0x56, 0xc3, 0x0a, 0x5e, 0x94, 0x5c, 0x42, 0x52, 0xf5, 0xa2, 0xe0, 0x27, 0x7a, 0x5a, 0x43, 0x13, 0x34, 0xb4, 0x6c, 0x21, 0x29, 0x29, 0x6e, 0x02, 0xd1, 0x48, 0x2e, 0x25, 0x25, 0x30, 0x16, 0x92, 0x90, 0x0b, 0x49, 0x49, 0x80, 0x51, 0x49, 0x00, 0x94, 0x55, 0x00, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x29, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x49, 0x40, 0x05, 0x14, 0x00, 0x51, 0x48, 0x02, 0x8a, 0x00, 0x4a, 0x28, 0x00, 0xa5, 0xa0, 0x42, 0x51, 0x40, 0x05, 0x14, 0xc6, 0x14, 0x52, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x29, 0x29, 0x88, 0x29, 0x69, 0x0c, 0x28, 0xa0, 0x42, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x9e, 0x8e, 0x2b, 0x60, 0x0a, 0x5a, 0x00, 0x28, 0x14, 0x00, 0x94, 0xb4, 0x0c, 0x4a, 0x29, 0x07, 0x40, 0xa2, 0xa4, 0x42, 0x1a, 0x3e, 0x94, 0xc0, 0x28, 0xa9, 0xd8, 0x04, 0xa5, 0xa6, 0x02, 0x51, 0xd6, 0x96, 0xe0, 0x14, 0x52, 0xb0, 0x05, 0x25, 0x30, 0x0a, 0x28, 0xb0, 0x0b, 0x49, 0x48, 0x02, 0x92, 0x8e, 0x80, 0x14, 0x52, 0x10, 0x51, 0x4c, 0x02, 0x8a, 0x40, 0x25, 0x2d, 0x03, 0x12, 0x8a, 0x60, 0x14, 0x50, 0x01, 0x45, 0x20, 0x0a, 0x28, 0x01, 0x29, 0x68, 0x10, 0x94, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0x40, 0x84, 0xa5, 0xa4, 0x30, 0xa2, 0x80, 0x12, 0x8a, 0x00, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x02, 0xc5, 0x15, 0xb3, 0x18, 0x52, 0x52, 0x10, 0xb4, 0x53, 0x60, 0x14, 0x94, 0x0c, 0x3b, 0x51, 0x4a, 0xe2, 0x0a, 0x29, 0x00, 0x94, 0x51, 0x6b, 0x80, 0x51, 0x48, 0x02, 0x8a, 0x40, 0x25, 0x14, 0xd8, 0x05, 0x15, 0x20, 0x25, 0x14, 0xc0, 0x28, 0xa0, 0x02, 0x8a, 0x9b, 0x08, 0x4a, 0x2a, 0x80, 0x28, 0xa9, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x01, 0x29, 0x68, 0x01, 0x28, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x28, 0x10, 0x94, 0x52, 0x18, 0xb4, 0x94, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x02, 0x12, 0x8a, 0x06, 0x14, 0xb4, 0x00, 0x94, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x93, 0xd1, 0x5a, 0xbe, 0xc8, 0x1e, 0xa1, 0x4b, 0xde, 0x82, 0x83, 0x34, 0x11, 0x48, 0x91, 0x05, 0x1d, 0xe9, 0xb1, 0x86, 0x69, 0x29, 0xd8, 0x42, 0xd1, 0x51, 0x24, 0x02, 0x51, 0x54, 0x01, 0x45, 0x4d, 0xc0, 0x29, 0x29, 0x00, 0x51, 0x45, 0xc0, 0x4e, 0xf4, 0x52, 0x00, 0xa2, 0xa8, 0x02, 0x8a, 0x80, 0x12, 0x8a, 0xa0, 0x0a, 0x28, 0x00, 0xa2, 0x90, 0x05, 0x14, 0x82, 0xe1, 0x45, 0x08, 0x04, 0xa2, 0x98, 0x05, 0x14, 0x84, 0x14, 0x50, 0x30, 0xa4, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0xb4, 0x0c, 0x4a, 0x5a, 0x04, 0x25, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0xc4, 0xa5, 0xa0, 0x42, 0x52, 0xd0, 0x31, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x09, 0xfa, 0xd2, 0xf7, 0xad, 0x87, 0x70, 0xdb, 0xf9, 0x52, 0x51, 0xab, 0x00, 0xa5, 0xa6, 0x3b, 0x09, 0x45, 0x40, 0x98, 0x51, 0xf5, 0xa6, 0x02, 0x51, 0x48, 0x42, 0xf5, 0xa2, 0x92, 0x01, 0x28, 0xa3, 0xa0, 0x82, 0x92, 0x90, 0xc2, 0x83, 0x43, 0x42, 0x0a, 0x4a, 0x43, 0x0a, 0x4a, 0x60, 0x14, 0xb4, 0x08, 0x29, 0x2a, 0x6e, 0x01, 0x45, 0x0c, 0x61, 0x45, 0x31, 0x05, 0x14, 0x80, 0x29, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x51, 0x48, 0x02, 0x92, 0x86, 0x01, 0x45, 0x17, 0x18, 0x52, 0xd0, 0x02, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x4a, 0x5a, 0x06, 0x25, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x20, 0xa2, 0x81, 0x93, 0xe2, 0x8a, 0xd6, 0x21, 0x71, 0x28, 0xaa, 0x60, 0x85, 0xcd, 0x15, 0x2c, 0x62, 0xd2, 0x66, 0x81, 0x58, 0x28, 0xa0, 0x02, 0x92, 0x90, 0x05, 0x14, 0x00, 0x52, 0x50, 0x01, 0x45, 0x20, 0x0a, 0x29, 0x00, 0x94, 0x55, 0x00, 0x51, 0x52, 0x01, 0x45, 0x00, 0x25, 0x2d, 0x48, 0x09, 0x45, 0x00, 0x14, 0x53, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x40, 0x14, 0x53, 0x00, 0xa2, 0x80, 0x0a, 0x4a, 0x40, 0x14, 0x53, 0x00, 0xa2, 0x90, 0x05, 0x14, 0xc0, 0x28, 0xa4, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x0c, 0x41, 0x49, 0x40, 0xc2, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x27, 0xa3, 0x81, 0x5a, 0xa6, 0x02, 0x52, 0xd2, 0xb8, 0x0b, 0x45, 0x58, 0xc6, 0x9a, 0x5a, 0x42, 0x0a, 0x2a, 0x40, 0x29, 0x28, 0x00, 0xa2, 0x8d, 0x80, 0x28, 0xa4, 0x02, 0x51, 0x40, 0x05, 0x14, 0x84, 0x25, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x3a, 0x80, 0x51, 0x52, 0x02, 0x51, 0x4c, 0x02, 0x8a, 0x04, 0x14, 0x52, 0x01, 0x28, 0xa6, 0x30, 0xa2, 0x81, 0x0b, 0x49, 0x48, 0x62, 0x52, 0xd0, 0x20, 0xa2, 0x80, 0x12, 0x96, 0x81, 0x89, 0x45, 0x17, 0x00, 0xa2, 0x81, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x52, 0x50, 0x31, 0x69, 0x28, 0x00, 0xa5, 0xa0, 0x04, 0xa2, 0x81, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x02, 0x6a, 0x5e, 0xd5, 0xa8, 0xd8, 0x94, 0xb4, 0xd8, 0x82, 0x8f, 0xad, 0x03, 0x0a, 0x2a, 0x6e, 0x21, 0x29, 0x68, 0x01, 0x28, 0xa1, 0x80, 0xb4, 0xda, 0x40, 0x2d, 0x25, 0x00, 0x14, 0x52, 0x00, 0xc5, 0x14, 0x00, 0x94, 0x55, 0x00, 0x51, 0x52, 0x17, 0x0a, 0x28, 0x60, 0x25, 0x14, 0x80, 0x29, 0x69, 0x88, 0x4a, 0x29, 0x0c, 0x28, 0xa4, 0x21, 0x29, 0x69, 0x8c, 0x4a, 0x28, 0x00, 0xa2, 0x90, 0x84, 0xa5, 0xa6, 0x01, 0x45, 0x20, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x06, 0x14, 0x50, 0x20, 0xa2, 0x98, 0x05, 0x14, 0x86, 0x25, 0x2d, 0x00, 0x14, 0x94, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x04, 0xf4, 0x13, 0xcd, 0x5e, 0xec, 0x61, 0xde, 0x8a, 0xad, 0x04, 0xc5, 0xa2, 0x9a, 0x01, 0x28, 0xe6, 0x98, 0x05, 0x15, 0x20, 0x26, 0x28, 0xa4, 0x01, 0x45, 0x4e, 0x80, 0x14, 0x94, 0xc0, 0x28, 0xa0, 0x41, 0x49, 0x4a, 0xc3, 0x16, 0x92, 0x90, 0x05, 0x14, 0x72, 0x80, 0x51, 0x40, 0x84, 0xa2, 0x80, 0x0a, 0x29, 0x80, 0x52, 0x52, 0x18, 0xb4, 0x1a, 0x42, 0x12, 0x96, 0x81, 0x89, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x4a, 0x00, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x52, 0x50, 0x02, 0xd1, 0x40, 0x82, 0x92, 0x81, 0x8b, 0x49, 0x40, 0x82, 0x8a, 0x00, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x58, 0xa4, 0xed, 0x5a, 0x80, 0xbd, 0xe9, 0x29, 0xa0, 0x61, 0x45, 0x26, 0x09, 0x05, 0x1d, 0x29, 0x80, 0x51, 0x52, 0x02, 0x51, 0x40, 0x05, 0x25, 0x00, 0x2e, 0x68, 0xa4, 0x21, 0x29, 0x69, 0x0c, 0x4a, 0x4a, 0x2e, 0x80, 0x5a, 0x29, 0x08, 0x4a, 0x28, 0x18, 0x51, 0x40, 0x09, 0x45, 0x30, 0x0a, 0x29, 0x00, 0x51, 0x40, 0x82, 0x92, 0x90, 0xc2, 0x96, 0x98, 0x84, 0xa2, 0x86, 0x01, 0x45, 0x03, 0x0a, 0x29, 0x00, 0x94, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x85, 0x25, 0x00, 0x14, 0xb4, 0x00, 0x94, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x00, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x01, 0x35, 0x2d, 0x6b, 0xb8, 0x30, 0xa2, 0x9a, 0xd0, 0x02, 0x8a, 0x40, 0x1d, 0xe8, 0xa0, 0x02, 0x8a, 0x24, 0xae, 0x01, 0x49, 0x40, 0x05, 0x14, 0x98, 0x05, 0x21, 0xa3, 0x60, 0x0a, 0x2a, 0x1b, 0xd4, 0x41, 0x49, 0x48, 0x05, 0xa4, 0xa0, 0x02, 0x8a, 0x63, 0x0a, 0x28, 0x10, 0x94, 0x50, 0x30, 0xa2, 0x93, 0x10, 0x51, 0x40, 0xc2, 0x92, 0x81, 0x05, 0x14, 0xc0, 0x28, 0xa0, 0x02, 0x8a, 0x4c, 0x61, 0x45, 0x00, 0x14, 0x94, 0xc0, 0x28, 0xa0, 0x02, 0x8a, 0x42, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x25, 0x00, 0x2d, 0x25, 0x02, 0x0a, 0x5a, 0x06, 0x14, 0x94, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x22, 0x7a, 0x53, 0x5a, 0x49, 0x8c, 0x4a, 0x28, 0x40, 0x14, 0x55, 0x0c, 0x4a, 0x5a, 0x04, 0xc4, 0xa5, 0xa9, 0xe6, 0x18, 0x51, 0x52, 0x98, 0x84, 0xa2, 0x98, 0x05, 0x25, 0x20, 0x0e, 0xd4, 0x50, 0x84, 0x25, 0x2d, 0x00, 0x25, 0x14, 0x0c, 0x28, 0xa4, 0x20, 0xa4, 0xaa, 0x18, 0x51, 0x52, 0xc4, 0x14, 0x52, 0x00, 0xa4, 0xa6, 0x31, 0x69, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x63, 0x0a, 0x28, 0x10, 0x94, 0xb4, 0x0c, 0x4a, 0x29, 0x00, 0x51, 0x40, 0x82, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x49, 0x40, 0x0b, 0x49, 0x40, 0x0b, 0x49, 0x40, 0x85, 0xa2, 0x81, 0x89, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4c, 0x69, 0xdf, 0x85, 0x69, 0x60, 0xe8, 0x37, 0xa7, 0x4a, 0x3a, 0x55, 0x00, 0xb4, 0x51, 0x60, 0x0a, 0x2a, 0x6c, 0x01, 0x9a, 0x4a, 0x56, 0xb3, 0x00, 0xa3, 0xa5, 0x30, 0x0a, 0x29, 0x08, 0x29, 0x28, 0x00, 0xa2, 0x90, 0x05, 0x14, 0x86, 0x14, 0x94, 0xc0, 0x28, 0xa4, 0x02, 0x52, 0xd0, 0x02, 0x51, 0x4c, 0x42, 0x52, 0xd2, 0x00, 0xa2, 0x93, 0x04, 0x14, 0x94, 0xc6, 0x2d, 0x25, 0x21, 0x05, 0x14, 0x0c, 0x4a, 0x5a, 0x04, 0x25, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x00, 0x14, 0x50, 0x01, 0x49, 0x40, 0xc2, 0x8a, 0x00, 0x5a, 0x4a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x0a, 0x28, 0x10, 0x51, 0x40, 0x05, 0x14, 0x0c, 0x28, 0xa0, 0x02, 0x8a, 0x04, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x27, 0xa2, 0xb5, 0x18, 0x94, 0xb4, 0x06, 0xe1, 0x4b, 0xda, 0x90, 0x31, 0x29, 0x7b, 0xd0, 0x21, 0x28, 0xa1, 0x80, 0x94, 0x52, 0xb0, 0x05, 0x14, 0xc0, 0x33, 0x49, 0x4b, 0xd0, 0x2c, 0x14, 0x52, 0x12, 0x0a, 0x4a, 0x06, 0x14, 0x52, 0x60, 0x14, 0x52, 0xb0, 0x05, 0x25, 0x16, 0x00, 0xa2, 0x98, 0x82, 0x8a, 0x40, 0x14, 0x50, 0x01, 0x49, 0x40, 0xc2, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x03, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x04, 0x14, 0x50, 0x01, 0x45, 0x00, 0x14, 0x50, 0x30, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x12, 0x8a, 0x04, 0x2d, 0x25, 0x03, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x27, 0xa0, 0x55, 0x94, 0x06, 0x92, 0xa8, 0x42, 0xd1, 0x9a, 0x34, 0x00, 0xa2, 0x86, 0x84, 0x25, 0x2d, 0x17, 0x01, 0x28, 0xa4, 0x01, 0x49, 0x46, 0xc0, 0x14, 0x52, 0x00, 0xa2, 0x90, 0x09, 0x45, 0x48, 0x05, 0x15, 0x40, 0x14, 0x52, 0x00, 0xa4, 0xa3, 0x98, 0x41, 0x45, 0x3b, 0x80, 0x51, 0x9a, 0x40, 0x14, 0x52, 0x18, 0x94, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x4c, 0x04, 0xa5, 0xa0, 0x02, 0x92, 0x90, 0x82, 0x8a, 0x00, 0x28, 0xa0, 0x61, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x52, 0x50, 0x20, 0xa5, 0xa0, 0x61, 0x49, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4d, 0x4b, 0x5a, 0x80, 0x51, 0x46, 0xc0, 0x25, 0x2d, 0x49, 0x48, 0x28, 0xa6, 0x26, 0x25, 0x2d, 0x21, 0x09, 0x45, 0x3b, 0x80, 0x51, 0x50, 0xc0, 0x4a, 0x28, 0x00, 0xa2, 0x98, 0x09, 0x45, 0x3e, 0x82, 0x0a, 0x2a, 0x6c, 0x30, 0xa2, 0x98, 0x09, 0x45, 0x48, 0x82, 0x8a, 0x63, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x12, 0x96, 0x80, 0x12, 0x8a, 0x5d, 0x40, 0x28, 0xa6, 0x01, 0x49, 0x48, 0x05, 0xa4, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x41, 0x45, 0x03, 0x12, 0x96, 0x80, 0x0a, 0x28, 0x00, 0xa2, 0x80, 0x0a, 0x28, 0x01, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x28, 0xa0, 0x02, 0x8a, 0x00, 0x9f, 0x9a, 0x2b, 0x5b, 0x8f, 0x70, 0xa2, 0x8b, 0x00, 0x52, 0x50, 0x90, 0x82, 0x96, 0x95, 0x80, 0x43, 0xcd, 0x2d, 0x00, 0x25, 0x14, 0x80, 0x28, 0xa0, 0x04, 0xa2, 0x81, 0x05, 0x14, 0x86, 0x14, 0x50, 0x02, 0x51, 0x4c, 0x02, 0x8a, 0x86, 0x01, 0x49, 0x46, 0xc2, 0x0a, 0x29, 0x8c, 0x28, 0xa0, 0x02, 0x92, 0x98, 0x82, 0x8a, 0x06, 0x14, 0x54, 0x88, 0x28, 0xa6, 0x30, 0xa4, 0xa4, 0x21, 0x68, 0xa0, 0x62, 0x51, 0x40, 0x85, 0xa4, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x21, 0x29, 0x68, 0x18, 0x51, 0x40, 0x05, 0x14, 0x08, 0x29, 0x28, 0x18, 0xb4, 0x94, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x4c, 0x7d, 0xe9, 0x7d, 0xaa, 0xef, 0xd8, 0x02, 0x8a, 0xae, 0x80, 0x14, 0xb4, 0x7a, 0x00, 0x9d, 0xa9, 0x0d, 0x2b, 0x80, 0xb4, 0x50, 0x02, 0x51, 0xd2, 0x90, 0x05, 0x14, 0x80, 0x29, 0x2a, 0x80, 0x31, 0x45, 0x20, 0x0a, 0x29, 0x00, 0x94, 0x52, 0x60, 0x25, 0x28, 0xa4, 0x02, 0x52, 0x55, 0x5c, 0x05, 0xa2, 0x90, 0x05, 0x14, 0xc0, 0x28, 0xa4, 0x01, 0x49, 0x40, 0x05, 0x14, 0x84, 0x14, 0x50, 0x01, 0x45, 0x17, 0x18, 0x52, 0x50, 0x20, 0xa2, 0x81, 0x85, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x82, 0x92, 0x81, 0x85, 0x2d, 0x02, 0x12, 0x8a, 0x06, 0x14, 0x50, 0x01, 0x45, 0x02, 0x0a, 0x28, 0x18, 0x51, 0x40, 0x05, 0x14, 0x00, 0x51, 0x40, 0x05, 0x14, 0x08, 0x28, 0xa0, 0x61, 0x45, 0x00, 0x14, 0x50, 0x01, 0x45, 0x00, 0x7f, 0xff, 0xd9}; +// 21:15:38.821 > [ 53028][I][CStreamer.cpp:207] streamFrame(): QTable0: Len=64 +static unsigned char jpeg_qtable0[64] = { + 0x0e, 0x0a, 0x0b, 0x0c, 0x0b, 0x09, 0x0e, 0x0c, 0x0b, 0x0c, 0x10, 0x0f, 0x0e, 0x11, 0x15, 0x23, + 0x17, 0x15, 0x13, 0x13, 0x15, 0x2b, 0x1f, 0x20, 0x19, 0x23, 0x33, 0x2d, 0x35, 0x35, 0x32, 0x2d, + 0x31, 0x30, 0x38, 0x3f, 0x51, 0x44, 0x38, 0x3c, 0x4c, 0x3c, 0x30, 0x31, 0x46, 0x5f, 0x47, 0x4c, + 0x53, 0x56, 0x5a, 0x5b, 0x5a, 0x36, 0x43, 0x63, 0x6a, 0x62, 0x58, 0x69, 0x51, 0x58, 0x5a, 0x57}; +// 21:15:42.410 > [ 56616][I][CStreamer.cpp:217] streamFrame(): QTable1: Len=64 +static unsigned char jpeg_qtable1[64] = { + 0x0f, 0x10, 0x10, 0x15, 0x12, 0x15, 0x29, 0x17, 0x17, 0x29, 0x57, 0x3a, 0x31, 0x3a, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, + 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57}; + +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + +void test_jpg_decode() +{ + jpg jpg; + TEST_ASSERT_TRUE(jpg.decode(reinterpret_cast(jpeg), sizeof(jpeg))); + TEST_ASSERT_EQUAL_INT32(sizeof(jpeg_data), jpg.jpeg_data_end - jpg.jpeg_data_start); + TEST_ASSERT_EQUAL_UINT8_ARRAY(jpeg_data, jpg.jpeg_data_start, sizeof(jpeg_data)); + + // Id is not stored + TEST_ASSERT_EQUAL_UINT8_ARRAY(jpeg_qtable0, jpg.quantization_table_luminance_->data, sizeof(jpeg_qtable0)); + // Id is not stored + TEST_ASSERT_EQUAL_UINT8_ARRAY(jpeg_qtable1, jpg.quantization_table_chrominance_->data, sizeof(jpeg_qtable1)); +} + +void test_struct_sizes() +{ + TEST_ASSERT_EQUAL(4, sizeof(rtp_over_tcp_hdr_t)); + TEST_ASSERT_EQUAL(12, sizeof(rtp_hdr_t)); + TEST_ASSERT_EQUAL(8, sizeof(jpeg_hdr_t)); + TEST_ASSERT_EQUAL(4, sizeof(jpeg_hdr_qtable_t)); + TEST_ASSERT_EQUAL(24, sizeof(jpeg_packet_t)); +} + +void test_bitfield() +{ + jpeg_hdr_t jpeg_hdr; + jpeg_hdr.tspec = 0x55; + jpeg_hdr.off = 0xAAAAAA; + TEST_ASSERT_EQUAL(0x55, jpeg_hdr.tspec); + TEST_ASSERT_EQUAL(0xAAAAAA, jpeg_hdr.off); + jpeg_hdr.tspec = 0xAA; + jpeg_hdr.off = 0x555555; + TEST_ASSERT_EQUAL(0xAA, jpeg_hdr.tspec); + TEST_ASSERT_EQUAL(0x555555, jpeg_hdr.off); +} + +void test_default() +{ + rtp_over_tcp_hdr_t rtp_over_tcp_hdr; + TEST_ASSERT_EQUAL('$', rtp_over_tcp_hdr.magic); +} + +void setup() +{ + // Disable brownout + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); + + Serial.begin(115200); + Serial.setDebugOutput(true); + + UNITY_BEGIN(); + RUN_TEST(test_jpg_decode); + RUN_TEST(test_struct_sizes); + RUN_TEST(test_bitfield); + RUN_TEST(test_default); + UNITY_END(); +} + +void loop() +{ +} \ No newline at end of file